Is it possible to replace a gesture template of template library from a running application?
I am building a handwriting recognizer system in which there are templates of letters in gesture library file.So basically after loading the library inside the code i compare user input gesture like:
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = gesturelib.recognize(gesture);
if (predictions.size() > 1) {
for(Prediction prediction: predictions){
//i compare prediction name here and if matches print it in an edittext
}
This should work good until user will give the same pattern like i did during building the library template.But i want to give an user that flexibility to replace an template item with his handwritten pattern when there is a mismatch of prediction.
Because below 2 handwritten gesture samples are different in terms of pattern,but not as a letter.Suppose,my system supports the 1st image pattern,i want when user will give 2nd image pattern the system will ask confirmation from user to replace it with the library pattern of A and then replace it after confirm.So next time the system will recognize user pattern much better.
Any help would be greatly appreciated.
If I understand correctly, you want to replace an already existing gesture with a new one?
So, when the user inputs a gesture that isn't in the library, your app asks the user to select which gesture they wish to replace? From your question, I will assume that when user draws a lowercase a(and if a isn't in the library), user is presented with a list of all available gestures/letters that your app currently supports. And then, the user selects capital A, and now, capital A must be replaced with lowercase a. In the following code, oldGesture is the Gesture corresponding to A. And newGesture is the Gesture just drawn.
The process for that would be: delete the old gesture, add the new one using old gesture's name. To delete a gesture, use GestureLibrary.removeGesture(String, Gesture):
public void onGesturePerformed(GestureOverlayView overlay, final Gesture gesture) {
ArrayList<Prediction> predictions = gesturelib.recognize(gesture);
if (predictions.size() > 1) {
for(Prediction prediction: predictions){
if (prediction.score > ...) {
} else {
if (user wants to replace) {
showListWithAllGestures(gesture);
}
}
}
}
}
public void showListWithAllGestures(Gesture newGesture) {
....
....
// User picks a gesture
Gesture oldGesture = userPickedItem.gesture;
String gestureName = userPickedItem.name;
// delete the gesture
gesturelib.removeGesture(gestureName, oldGesture);
gesturelib.save();
// add gesture
gesturelib.addGesture(gestureName, newGesture);
gesturelib.save();
}
To get a list of all available gestures:
// Wrapper to hold a gesture
static class GestureHolder {
String name;
Gesture gesture;
}
Load gestures using GestureLibrary.load():
if (gesturelib.load()) {
for (String name : gesturelib.getGestureEntries()) {
for (Gesture gesture : gesturelib.getGestures(name)) {
final GestureHolder gestureHolder = new GestureHolder();
gestureHolder.gesture = gesture;
gestureHolder.name = name;
// Add `gestureHolder` to a list
}
}
// Return the list that holds GestureHolder objects
}
Edit:
Sorry, but the check I have suggested: if (wants to replace) is being carried out at the wrong place in code.
if (predictions.size() > 1) {
// To check whether a match was found
boolean gotAMatch = false;
for(int i = 0; i < predictions.size() && !gotAMatch; i++){
if (prediction.score > ... ) {
....
....
// Found a match, look no more
gotAMatch = true;
}
}
// If a match wasn't found, ask the user s/he wants to add it
if (!gotAMatch) {
if (user wants to replace) {
showListWithAllGestures(gesture);
}
}
}
Related
I have Android WebView which displays some links as: Link1TextLink2Text Now I would like to retrieve Link1Text and Link2Text when I long press these links. I have contextMenu implemented in the code and I could successfully get the link urls (http://link1.html, http://link2.html) using HitTestResult getExtra() method but how ccan I get those link texts ?FYI, I require those link texts for implementing "Copy link text" option in the contextMenu.
To get the text of an achor link:
I. Hook a touchstart listener to every web pages in the onPageFinished() callback of WebViewClient via evaluateJavascript. like:
//Javascripts to evaluate in onPageFinished
const w=window;
w.addEventListener('touchstart',wrappedOnDownFunc);
function wrappedOnDownFunc(e){
if(e.touches.length==1){
w._touchtarget = e.touches[0].target;
}
console.log('hey touched something ' +w._touchtarget);
}
note we've saved the touch target.
II. Then implement OnLongClicklisenter for webview. use evaluateJavascript again when you long pressed on a link object:
#Override
public boolean onLongClick(View v) {
WebView.HitTestResult result = ((WebView)v).getHitTestResult();
if (null == result) return false;
int type = result.getType();
switch (type) {
case WebView.HitTestResult.SRC_ANCHOR_TYPE:
if(result.getExtra()!=null){
((WebView)v).evaluateJavascript("window._touchtarget?window._touchtarget.innerText:''", new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
System.out.println("hey received link text : "+value);
}
});
}
return true;
}
return false;
}
What's more, we can even choose to select the text of the anchor element! Actually this is one of the options that samsung browser offers when you long-pressed an tag .
To achieve this, we still need that recorded touch target. Besides we need 2 new javascript methods:
function selectTouchtarget(){
var tt = w._touchtarget;
if(tt){
w._touchtarget_href = tt.getAttribute("href");
tt.removeAttribute("href");
var sel = w.getSelection();
var range = document.createRange();
range.selectNodeContents(tt);
sel.removeAllRanges();
sel.addRange(range);
}
}
function restoreTouchtarget(){
var tt = w._touchtarget;
if(tt){
tt.setAttribute("href", w._touchtarget_href);
}
}
Finnaly in the onLongClick listener, instead of just fetch the innerText, we programmatically set the selection, trigger the action menu bar, and restore the removed href attribute of our touch target.
case WebViewmy.HitTestResult.SRC_ANCHOR_TYPE:
if(result.getExtra()!=null){
WebViewmy mWebView = ((WebViewmy)v);
mWebView.evaluateJavascript("selectTouchtarget()", new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
/* bring in action mode by a fake click on the programmatically selected text. */
MotionEvent te = MotionEvent.obtain(0,0,KeyEvent.ACTION_DOWN,mWebView.lastX,mWebView.lastY,0);
mWebView.dispatchTouchEvent(te);
te.setAction(KeyEvent.ACTION_UP);
mWebView.dispatchTouchEvent(te);
te.recycle();
//if it's not delayed for a while or the href attribute is not removed, then the above code would click into
// the anchor element instead of select it's text.
/* restore href attribute */
mWebView.postDelayed(() -> mWebView.evaluateJavascript("restoreTouchtarget()", null), 100);
}
});
}
return true;
In my case, I've extended the WebView as WebViewmy to record last touched positions, lastX and lastY, in the onTouchEvent method.
Unfortunately, a clear, official way to do this is not available. Although, there are two APIs (selectText and copySelection) which are pending API council approval, that may help to do this, but they are not available at the moment.
I have one screen where the user creates a gesture, then the user presses Next and on the Next screen it asks the user to confirm that gesture. Basically I want the gesture stored as a password. The gesture creation works fine, I have the following lines of code which store the gesture in the device's memory:
GestureLibrary store = GestureLibraries.fromRawResource(this, R.raw.gestures);;
store.addGesture("Gesture Password", mGesture);
store.save();
setResult(RESULT_OK);
I'm still messing around with how to recognize the gesture but for now I'm just trying to figure out how to compare against this stored gesture in memory. I have the following:
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = gestureLib.recognize(gesture);
for (Prediction prediction : predictions) {
if (prediction.score > 1.0) {
Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
}
}
}
Where:
private GestureLibrary gestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
As I understand, on the first screen I create the gesture, it's stored in raw.gestures, then I try accessing it again in the confirm screen and if the confirm gesture is similar enough, the toast should return "Gesture Password". But this doesn't work for some reason, what am I missing? Am I storing and retrieving the gesture incorrectly?
I am new to Unity. I am following the car tutorial and trying to port it to Android. Some how I managed to move the car in device. The problem is that I am using a 3D text which will be clicked to accelerate the car. What I did is
Created a 3D Text. Added box collider to it. Check the is Trigger option of Box Collider. Added the following script.
public var Mainref:TouchPlaneScript;
function FixedUpdate()
{
var touch: Touch = Input.touches[0];
if(touch.phase == TouchPhase.Began)
{
Mainref.applyBrake = true;
}
if(touch.phase == TouchPhase.Ended)
{
Mainref.applyBrake = false;
}
}
function Start ()
{
// Find the OtherScript which is attached to any game object in the scene.
Mainref = FindObjectOfType(TouchPlaneScript);
}
function OnMouseUp()
{
Mainref.applyBrake = false;
Debug.Log("Stop Brake");
}
function OnMouseDown()
{
Mainref.applyBrake = true;
Debug.Log("Apply Brake");
}
The logic inside the Touch Methods might be wrong don't worry about that. I have also commented the code for mouse functions while running it on device. But the problem remains the same.
THE PROBLEM IS THAT TOUCH METHODS ARE CALLED IF TOUCHED ON THE SCREEN ANY WHERE I WANT TOUCH FUNCTIONS TO BE CALLED ONLY WHEN CLICKED ON THE TEXT.
Please note that I have four buttons on the scene. left,right,brake,accel all are 3d text and have the same structure and same problem.
Your code have detect the click event by checking input touches, but you didn't check the position of the target, so once you click on the screen, every thing happens. You need to check the position of the touch to make sure you are doing the right operation. Code below(not familiar with JS, this is C# version, you need to translate it on your own):
void FixedUpdate ()
{
if ( Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.Android )
{
if ( Input.touchCount <= 0 )
return;
// detect single touch only
Touch touch = Input.touches[0];
if ( touch.phase == TouchPhase.Began )
{
Debug.Log( 123 );
OnTouchBegan( touch.position );
}
}
else
{
if ( Input.GetMouseButtonDown( 0 ) )
{
Debug.Log(Input.mousePosition);
OnTouchBegan( Input.mousePosition );
}
}
}
void OnTouchBegan (Vector2 screenPos)
{
Ray ray = Camera.main.ScreenPointToRay( screenPos );
RaycastHit hit;
if ( Physics.Raycast( ray, out hit ) )
{
hit.collider.gameObject.SendMessage("OnClick", SendMessageOptions.DontRequireReceiver);
}
}
after this, you need to create a new script implementing a method OnClick() and attach it on your 3D text game object. Then your 3D text will receive the OnClick message when you click on it.
Hope this helps.
By the way, if there is more than one camera in your scene, you need to change Camera.main to the camera which sees the 3D text.
You should look at Raycast in Unity, to make sure that the 3D text is well touched.
You can check the documentation at the section "Mobile input"
I have done a database for the suggestion words
but where to put it into the android soft keyboard example and how to use the words from db in the program? so that I will not need to type the word completely and it will shown the suggestion word in database
Inside the SDK check out the Samples folder, this contains a soft keyboard example and more information on how to suggest results.
You just need to handle database in SoftKeyboard.java Class.
To get the suggestion words from .db, please use SQLiteOpenHelper or SQLiteAssetsHelper.
To show the suggestion words in candidate view, please modify the updateCandidates() method of SoftKeyboard.java file in Google SoftKeyboard example project.
/**
* Update the list of available candidates from the current composing
* text. This will need to be filled in by however you are determining
* candidates.
*/
private void updateCandidates() {
if (!mCompletionOn) {
// mComposing is current text you typed.
if (mComposing.length() > 0) {
// Get suggested words list from your database here.
ArrayList<String> list = new ArrayList<String>();
list.add(mComposing.toString());
// This method will show the list as suggestion.
setSuggestions(list, true, true);
} else {
setSuggestions(null, false, false);
}
}
}
To enter the picked word from candidate view to input text, please modify following method in SoftKeyboard example project.
public void pickSuggestionManually(int index) {
if (mCompletionOn && mCompletions != null && index >= 0
&& index < mCompletions.length) {
CompletionInfo ci = mCompletions[index];
getCurrentInputConnection().commitCompletion(ci);
if (mCandidateView != null) {
mCandidateView.clear();
}
updateShiftKeyState(getCurrentInputEditorInfo());
} else if (mComposing.length() > 0) {
// If we were generating candidate suggestions for the current
// text, we would commit one of them here. But for this sample,
// we will just commit the current text.
commitTyped(getCurrentInputConnection());
// You need to add getter method for suggested words shown in candidate view
}
}
Hi i am following this tutorial
http://www.vogella.de/articles/AndroidGestures/article.html
i want to create an application in which user can add his gesture inmy application and then use it for authentication.i know using this code i can check whether gesture entered by him is correct or not.
package de.vogella.android.gestures;
import java.util.ArrayList;
public class GestureTest extends Activity implements OnGesturePerformedListener {
private GestureLibrary gestureLib;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GestureOverlayView gestureOverlayView = new GestureOverlayView(this);
View inflate = getLayoutInflater().inflate(R.layout.main, null);
gestureOverlayView.addView(inflate);
gestureOverlayView.addOnGesturePerformedListener(this);
gestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!gestureLib.load()) {
finish();
}
setContentView(gestureOverlayView);
}
#Override
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = gestureLib.recognize(gesture);
for (Prediction prediction : predictions) {
if (prediction.score > 1.0) {
Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT)
.show();
}
}
}
}
ok but please help me that how to add in gesture in R.raw.animate file.please suggest any way or link for adding a gesture in android app .
Extracted from here :
Android 1.6 and higher SDK platforms include a new application
pre-installed on the emulator, called Gestures Builder. You can use
this application to create a set of pre-defined gestures for your own
application...
...
As you can see, a gesture is always associated with a name. That name
is very important because it identifies each gesture within your
application. The names do not have to be unique. Actually it can be
very useful to have several gestures with the same name to increase
the precision of the recognition. Every time you add or edit a gesture
in the Gestures Builder, a file is generated on the emulator's SD
card, /sdcard/gestures. This file contains the description of all the
gestures, and you will need to package it inside your application
inside the resources directory, in /res/raw.
Here you have the source code of Gesture Builder
Gesture builder is installed in the emulator , but you can download it from here
And gesture source code examples here
Also, you may need to call gestureLib.load() before using it
Source code of gesture builder:
https://android.googlesource.com/platform/development/+/master/apps/GestureBuilder/