I am trying to implement contextual voice commands in my Glass application described in the documentation.
I have a FrameLayout inside my layout, and in my activity I'm implementing OnKeyDown in order to recognize taps. However, when the user says "Ok glass" and then selects one of the available commands, the same activity is returned, but unresponsive (I can't even close the app by sliding down).
I tried to use requestFocus() on the FrameLayout in a couple of different ways, but it did not have any effects. How could I have the focus back without having to restart the activity?
Essentially, this is the code I have so far for the main activity:
public class MainActivity extends Activity {
public static String TAG = "DummyProject::MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(WindowUtils.FEATURE_VOICE_COMMANDS);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreatePanelMenu(int featureId, Menu menu) {
if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS) {
getMenuInflater().inflate(R.layout.main, menu);
return true;
}
return super.onCreatePanelMenu(featureId, menu);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.layout.main, menu);
return true;
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS) {
switch (item.getItemId()) {
case R.id.awesome:
Log.i(TAG, "Selected!");
break;
default:
return true;
}
return true;
}
return super.onMenuItemSelected(featureId, item);
}
#Override
public boolean onKeyDown(int keycode, KeyEvent event) {
if(keycode == KeyEvent.KEYCODE_DPAD_CENTER) {
Log.i(TAG, "tap!");
return true;
}
return super.onKeyDown(keycode, event);
}
}
For this example, onKeyDown does not get called after I select any of the "ok glass" menu options.
Thank you in advance.
prefer GestureDetector for catching touch pad events...
...
private GestureDetector mGestureDetector;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
mGestureDetector = createGestureDetector(this);
...
}
...
private GestureDetector createGestureDetector(Context context) {
GestureDetector gestureDetector = new GestureDetector(context);
// Create a base listener for generic gestures
gestureDetector.setBaseListener(new GestureDetector.BaseListener() {
#Override
public boolean onGesture(Gesture gesture) {
if (gesture == Gesture.TAP) {
Log.d(TAG, "TAP!!!");
return true;
}
return false; }
});
gestureDetector.setFingerListener(new GestureDetector.FingerListener() {
#Override
public void onFingerCountChanged(int previousCount, int currentCount) {
// do something on finger count changes
}
});
gestureDetector.setScrollListener(new GestureDetector.ScrollListener() {
#Override
public boolean onScroll(float displacement, float delta, float velocity) {
// do something on scrolling
return true;
}
});
return gestureDetector;
}
/*
* Send generic motion events to the gesture detector
*/
#Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (mGestureDetector != null) {
return mGestureDetector.onMotionEvent(event);
}
return false;
}
It turns out that the problem was with the Manifest file. I was setting a theme to the application, ie.
<application android:theme="#android:style/Theme.NoTitleBar"> ...
Once I removed the theme, everything worked perfectly. The GDK demo sample by Google was helpful when I was trying to find this odd error.
Related
(Sorry for changing the whole question as I found the actual problem after troubleshooting)I have my activity as followed:
public class MyAppActivity extends AppCompatActivity{
#Override
protected void onCreate(...)
{
//...
this.setContentView(contentViewResID);
Toolbar toolbar = (Toolbar) this.findViewById(toolbarResID);
this.setSupportActionBar(toolbar);
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
protected void onPause() {...}
#Override
protected void onResume() {...}
#Override
public boolean onSupportNavigateUp() {
Log.d("onSupportNavigateUp()", "pressed");
finish();
return super.onSupportNavigateUp();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {...}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {...}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item == menuAddFood) {
Intent intent = new Intent(this, ActivityAddFood.class);
this.startActivity(intent);
}
if (item == menuSettings){
Intent intent = new Intent(this, ActivitySetting.class);
this.startActivity(intent);
}
if(item == menuUsername){
}
return true;
}
}
EDIT:
After my troubleshooting, I found out after override the onOptionsItemSelected(), onSupportNavigateUp() no longer fired anymore when I pressed the top left BACK / UP / HOME button. I want to do finish() inside onSupportNavigateUp() How to solve this?
You have to override the method in your current Activity and call the super:
public class ActivityExample extends MyAppActivity {
Context context = this;
AppCompatActivity activity = this;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.createMyView(R.layout.activity_log_in, R.id.toolbar);
// ...
}
#Override
public boolean onSupportNavigateUp() {
finish();
return true;
}
}
Also, if you override onOptionsItemSelected, then onSupportNavigateUp will not be called.
//DONT OVERRIDE THIS METHOD
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
break;
}
return true;
}
I am trying to make a simple app: there is one button in the middle which a child would press. As long as that button is held down it would play a certain MP3.
At the moment, I tried with onClick, but, that plays only when the button is released.
Instead of using an onClickListener which exposes nothing more then an interface for press and release, you would need to use an onTouchListener - which exposes all touch events of a view.
myButton.setOnTouchListener( new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
MotionEvent.ACTION_DOWN:
// start playing
return true;
MotionEvent.ACTION_UP:
// stop playing
return true;
}
return false;
}
});
Try something like this. Using the boolean "playing" you can create a thread/loop elsewhere to check if still playing and keep audio going.
button.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
if (arg1.getAction()==MotionEvent.ACTION_DOWN) {
playing = true;
} else {
playing = false;
}
return true;
}
});
Try the OnFocusChangeListener
Button.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
// code to execute when Button loses focus, i.e. stop music
}
}
});
Since a button is a view component you can use View.OnTouchListener event listener with ACTION_BUTTON_PRESS & ACTION_BUTTON_RELEASE MotionEvent.
Here is an example:
yourButton.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_BUTTON_PRESS){
// Start Video
return true;
} else if (event.getAction() == MotionEvent.ACTION_BUTTON_RELEASE) {
// End Video
return true;
}
return false;
}
});
This is my code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start_recording(View view){
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.test1);
mediaPlayer.start();
}
}
I have a XML layout, on which I'm applying OnTouchListener, which task is to detect finger swipe direction; anyway, it's working only when swipe is performed just on layout, but not on it's items (like ImageViews, Buttons etc.). How do I rewrite it to make swipe working on whole layout, but avoid creating dozens of Listeners for all items on it?
Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_layout"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
>
</RelativeLayout>
Code:
View relative = findViewById(R.id.main_layout);
relative.setOnTouchListener(...)
Because you are setting OnclickListener for only one view which is parent. so that's why there is only one click response.
You can try this.
Button button1 = (Button) findviewbyid(R.id.buttonid);
button.setOnTouchListener(...)
Similarly images or other views.
Edit -
DO this for every view that you want to listn swipe for.
ImageView im = (ImgaeView) findviewbyid(R.id.imageid)
im.setOnTouchListener(...)
Similarly with Every View for Listning Swipe.
EDIT- So you don't wanna make more ONTouchListener. Make another class which implements OnTouchListener
public class Mytouchlistener implements OnTouchlistener{
#Override
public boolean onTouch(View v, MotionEvent event) {
HERE PUT YOUR CODE.
}
Then
Youanyview.OnTouchlistener(MyTouchlistener.class);
Got the idea???
you can implement View.OnTouchListener as shown below
public class SomeClass implements View.OnTouchListener {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()){
case R.id.view1:
//do something
break;
case R.id.view2:
//do something here too
break;
default:
break;
}
return false;
}
}
be aware that you must use setOnTouchListener .
good luck .
You can use following code to make a perfect android gesture:
Type following code at Main_activity.java:
package com.androidtutorialpoint.myapplication;
public class MainActivity extends AppCompatActivity implements
GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener {
private TextView output_text;
private GestureDetectorCompat DetectMe;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
output_text = (TextView) findViewById(R.id.outputText); // Taking reference of text to be displayed on screen
DetectMe = new GestureDetectorCompat(this,this);
DetectMe.setOnDoubleTapListener(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
// Following functions are overrided to show text when a particular method called.
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
output_text.setText("onSingleTapConfirmed");
return true;
}
#Override
public boolean onDoubleTap(MotionEvent e) {
output_text.setText("onDoubleTap");
return true;
}
#Override
public boolean onDoubleTapEvent(MotionEvent e) {
output_text.setText("onDoubleTapEvent");
return true;
}
#Override
public boolean onDown(MotionEvent e) {
output_text.setText("onDown");
return true;
}
#Override
public void onShowPress(MotionEvent e) {
output_text.setText("onShowPress");
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
output_text.setText("onSingleTapUp");
return true;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
output_text.setText("onScroll");
return true;
}
#Override
public void onLongPress(MotionEvent e) {
output_text.setText("onLongPress");
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
output_text.setText("onFling");
return true;
}
#Override
public boolean onTouchEvent(MotionEvent event){
this.DetectMe.onTouchEvent(event);
return super.onTouchEvent(event);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
public class MainActivity2 extends ActionBarActivity {
private static final String TAG = "Test Opencv Loadback";
public static String imgPath;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS: {
Log.i(TAG, "OpenCV loaded successfully");
}
break;
default: {
super.onManagerConnected(status);
}
break;
}
}};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display);
Intent intent = getIntent();
//get path from Intent
imgPath = intent.getStringExtra(MainActivity.PATH_NAME);
//view image using setbitmap
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main_activity2, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onResume() {
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10, this, mLoaderCallback);
}
}
The status value is getting set to 2, even though the OpenCV manager is installed on the phone. Need help in resolving the issue.When prompted to install opencv manager, it returns package installation failed
Well I figured it out myself. This was because the version code in initAsnyc was set to OPENCV_VERSION_2_4_10 whereas the openCV manager version was 2.4.9. So changed the version in initAsync to OPENCV_VERSION_2_4_9.
I have one imageview, if i touch the imageview it to do some action else if i double click that imageview need to do some action.
How it is possible.?
First create a GestureDetector and a listener. Then bind it to your class that extends GestureDetector.SimpleOnGestureListener.
private GestureDetector detector;
private ImageView mImageView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
detector = new GestureDetector(this, new MyGesturesListener());
// TODO find your image view
mImageView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
detector.onTouchEvent(event);
return true;
}
});
}
Then you can implement the methods of different gestures:
class MyGesturesListener extends GestureDetector.SimpleOnGestureListener{
#Override
public boolean onSingleTapUp(MotionEvent ev) {
// TODO handle single tap
return true;
}
#Override
public boolean onDoubleTap(MotionEvent ev) {
// TODO handle double tap
return true;
}
}