Why won't popUpMenu show on KeyEvent? - java

I have a video view that is full screen and would like to trigger a popupMenu when a certain key is pressed. The log shows that the key event is captured, but the popup view will not show. Any ideas why?
#Override
public boolean onKeyDown(int keyCode , KeyEvent event ){
switch(keyCode){
case KeyEvent.KEYCODE_DPAD_CENTER:
Log.i("POP uP MENU","Show");
mVideoView.pause();
showPopupMenu(new View(VideoPlayer.this));
case KeyEvent.KEYCODE_D:
popupMenu.dismiss();
}
return true;
}
private void showPopupMenu(View v){
popupMenu = new PopupMenu(VideoPlayer.this, v);
if(bitRates != null){
for(int i=0;i<bitRates.size();i++){
int menuItem = i;
popupMenu.getMenu().add(0,menuItem, 0,qualityList.get(i)+" : "+bitRates.get(i));
}
}
popupMenu.show();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(final MenuItem item) {
progressDialog = ProgressDialog.show(VideoPlayer.this, "", "Loading video...");
final int position = mVideoView.getCurrentPosition();
new Thread() {
public void run() {
try{
runOnUiThread(new Runnable() {
public void run() {
play(streamUrls.get(item.getItemId()),position);
}
});
}
catch (Exception e)
{
Log.e("tag", e.getMessage());
}
progressDialog.dismiss();
}
}.start();
return true;
}
});
}

It seems that
KeyEvent.KEYCODE_DPAD_CENTER
is an event that is set to be triggered by the VideoView by default. So when I pressed that key VideoView triggered its event event instead of the event I was requesting it to. I changed the KeyEvent KEYCODE to another key(One not used by Videoview) and it worked.

Related

Android Things onTouch doesnt release GPIO

I am using Android Things v1 and trying to use an on-screen Button to activate a motor as long as the button is pressed (tap & long press).
The problem I have is once the button is pressed the motor will not stop. I would like it to stop once the button is released.
Here is the button code:
mtrbtnGD.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
mtrGpio = manager.openGpio("BCM24");
mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE);
mtrGpio.setActiveType(Gpio.ACTIVE_HIGH);
mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mtrGpio.setValue(true);
Log.i(TAG, "Motor started");
}
catch (IOException e) {
Log.w(TAG, "Unable to access GPIO", e);
}
return true;
}
});
EDIT:
Here is the new code from Sam's reply:
public class MainActivity extends Activity {
private Gpio mtrGpio;
private GestureDetector mtrbtnGD;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mtrbtnGD = (Button) findViewById(R.id.mtrbtn);
Button closebtn = (Button) findViewById(R.id.closebtn);
Button stopmtrbtn = (Button) findViewById(R.id.stopmtrbtn);
final PeripheralManager manager = PeripheralManager.getInstance();
List<String> portList = manager.getGpioList();
if (portList.isEmpty()) {
Log.i(TAG, "No GPIO port available on this device.");
} else {
Log.i(TAG, "List of available ports: " + portList);
}
mtrbtnGD.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
mtrGpio = manager.openGpio("BCM24");
mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE);
mtrGpio.setActiveType(Gpio.ACTIVE_HIGH);
mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mtrGpio.setValue(true);
Log.i(TAG, "Motor started");
return true; // if you want to handle the touch event
case MotionEvent.ACTION_UP:
// RELEASED
mtrGpio.close();
return true; // if you want to handle the touch event
}
}
catch (IOException e) {
Log.w(TAG, "Unable to access GPIO", e);
}
return true;
}
});
The motor still doesn't stop when I release the on-screen button.
close() closes your connection to the GPIO peripheral, it does not change the value of that connection before closing it. You need to use setValue(false); as so:
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
mtrGpio = manager.openGpio("BCM24");
mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE);
mtrGpio.setActiveType(Gpio.ACTIVE_HIGH);
mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mtrGpio.setValue(true);
Log.i(TAG, "Motor started");
return true; // if you want to handle the touch event
case MotionEvent.ACTION_UP:
// RELEASED
mtrGpio.setValue(false); // ADD THIS
mtrGpio.close();
return true; // if you want to handle the touch event
}
Ideally, if you expect the motor to be turned on and off a lot, you should keep the connection open.
public class MainActivity extends Activity {
private Gpio mtrGpio;
private GestureDetector mtrbtnGD;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mtrbtnGD = (Button) findViewById(R.id.mtrbtn);
try {
PeripheralManager manager = PeripheralManager.getInstance();
mtrGpio = manager.openGpio("BCM24");
mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE);
mtrGpio.setActiveType(Gpio.ACTIVE_HIGH);
mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
} catch (IOException e) {
throw new IllegalStateException("cannot open gpio", e);
}
mtrbtnGD.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
mtrGpio.setValue(true);
Log.i(TAG, "Motor started");
return true;
case MotionEvent.ACTION_UP:
// RELEASED
mtrGpio.setValue(false);
return true;
}
} catch (IOException e) {
Log.w(TAG, "Unable to access GPIO", e);
}
return true;
}
});
}
#Override
protected void onDestroy() {
try {
mtrGpio.close();
} catch (IOException ignore) {
Log.w(TAG, "Unable to close GPIO", ignore);
}
super.onDestroy();
}
You can use this code inside onTouch method and Check event.getAction() :
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
return true; // if you want to handle the touch event
case MotionEvent.ACTION_UP:
// RELEASED
return true; // if you want to handle the touch event
}

A button that shows how long time it gets pressed

I wanna make a button that can show me how long time it gets pressed. If the button stops to get pressed the time still stays there, then you can keep pressing it. How can i do this?
With this code, I made a 5 second button-press open a new activity :)
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1=(Button)findViewById(R.id.button1);
final Handler handel = new Handler();
button1.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent arg1) {
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN:
handel.postDelayed(run, 5000/* OR the amount of time you want */);
break;
default:
handel.removeCallbacks(run);
break;
}
return true;
}
Runnable run = new Runnable() {
#Override
public void run() {
Intent i = new Intent(MainActivity.this, SecActivity.class);
startActivity(i);
}
};});
}}
if your mean a Button count the times it's pressed you can use:
int count = 0;
(your button).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
count++;
}
});
if you mean the longer you hold it you can use:
long time = 0;
(your button).setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction() == event.ACTION_DOWN){
time = System.currentTimeMillis();
}else if( event.getAcion() == event.ACTION_UP){
time = System.currentTimeMillis() - time;
}
return true;
}
});
note: that your variables like (int count) and (long time) should be declared in the body of your class not into a method;
below code is a example code for recognizing double click on a view with Custom time;
boolean isPressed = false;
long delayed = 1000;
final Hanlder handler = new Handler();
Button b;
b.setOnClickListener(new View.onClickListener(){
public void onClick(View v){
if(isPressed == true){
// recognize double click;
}else{
Toast.makeText(getApplicationContext(),"tap again to exit",1).show();
isPressed = true;
handler.postDelayed(new Runnable(){
public void run(){
isPressed = false;
}
},delayed);
}
});
Try TouchListener:
Handler handel = new Handler();
b.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN:
handel.postDelayed(run, 5000);
break;
default:
handel.removeCallbacks(run);
break;
}
return true;
}
});
Later define run:
Runnable run = new Runnable() {
#Override
public void run() {
// Your code to run on long click
}
};
Set a listener for when the button is pressed and when the button is released. Create a timer that records after the button is pressed and stops when the button is released. There should be listeners for both if you are using JFrame or Android as your GUI.

button.PerformClick() causing text to clear

I have an activity where a user sends messages to another user, I created an onKey listener to send messages when a user pressed enter as well.
When a user actually clicks the send button, everything works perfectly, when a user presses the enter button a blank message is sent.
Here is the onkeylistener code
Code:
messageText.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == 66) {
sendMessageButton.performClick();
return true;
}
return false;
}
});
and this is the sendmessagebutton
Code:
sendMessageButton.setOnClickListener(new OnClickListener() {
CharSequence message;
Handler handler = new Handler();
#Override
public void onClick(View arg0) {
// android.text.format.DateFormat df = new
// android.text.format.DateFormat();
message = messageText.getText();
String messageSent = DateFormat.format("dd MMM yy, kk:mm",
new java.util.Date()).toString();// java.text.DateFormat.getDateTimeInstance().format("yyyy-MM-dd kk:mm:ss");
if (message.length() > 0) {
appendToMessageHistory(imService.getUsername(),
message.toString(), messageSent);
((ScrollView) findViewById(R.id.scrollView))
.fullScroll(View.FOCUS_DOWN);
localstoragehandler.insert(imService.getUsername(),
friend.userName, message.toString(), messageSent);
messageText.setText("");
Thread thread = new Thread() {
#Override
public void run() {
try {
if (imService.sendMessage(
imService.getUsername(),
friend.userName, message.toString()) == null) {
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(
getApplicationContext(),
R.string.message_cannot_be_sent,
Toast.LENGTH_LONG).show();
// showDialog(MESSAGE_CANNOT_BE_SENT);
}
});
}
} catch (UnsupportedEncodingException e) {
Toast.makeText(getApplicationContext(),
R.string.message_cannot_be_sent,
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
};
thread.start();
}
}
});
When user clicks button
message = messageText.getText();// get message
Then you do
messageText.setText("");
So when user presses the enter button in onKey you have sendMessageButton.performClick() a blank message is sent since you already set messageText.setText("")

Android: Toggle button doesnt update

I'm having some problems trying to set togglebutton (LeftLightButton) state and text after receiving value 1 at novo.charAt(0) for example. The main idea is, i click the button, it makes webview.loadUrl, and if the page changes to what i expected the toggle button state should be on, if not, it must stay off and vice versa. The way it is now, doesnt change the text neither state in case the site didnt update to the value that i was expecting.
public class MainActivity extends Activity {
private WebView webView;
private ToggleButton LeftLightButton;
private Thread webviewthread;
private String baseURL;
private boolean LeftLightButtonState;
public void onCreate(Bundle savedInstanceState) {
final Context context = this;
baseURL = "http://192.168.1.4/i.php";
LeftLightButton = (ToggleButton) findViewById(R.id.toggleButton1);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runOnUiThread(new Runnable() {
public void run()
{
synchronized(this) {
webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(context, "HTMLOUT");
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
webView.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
}
});
webView.loadUrl(baseURL);
}
}
});
showToast("Getting current status...");
}
public void notify(final boolean state, final ToggleButton buttonName) {
Thread thread = new Thread() {
#Override
public void run() {
synchronized (this) {
try {
wait(1000);
final ToggleButton button = (ToggleButton) findViewById(R.id.toggleButton1);
if (!state && button.isChecked()) {
showToast("Couldnt turn OFF");
// UI
runOnUiThread(new Runnable() {
#Override
public void run() {
button.setChecked(false);
button.setTextOff("OFF");
}
});
// end of UI
}
if (state && !button.isChecked()) {
showToast("Couldnt turn ON");
// UI
runOnUiThread(new Runnable() {
#Override
public void run() {
button.setChecked(true);
button.setTextOn("ON");
}
});
// end of UI
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
thread.start();
}
public void showToast(final String toast)
{
runOnUiThread(new Runnable() {
public void run()
{
Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
}
});
}
public void onClick(View arg0) {
final int id = arg0.getId();
switch (id) {
case R.id.toggleButton1:
if (LeftLightButtonState == true) {
webView.loadUrl(baseURL+"?L=0");
notify(false, LeftLightButton);
} else {
webView.loadUrl(baseURL+"?L=1");
notify(true, LeftLightButton);
}
break;
// even more buttons here
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void processHTML(String html) { // <html> <body> 1 0 0 0 </body> </html>
LeftLightButton = (ToggleButton) findViewById(R.id.toggleButton1);
String novo = android.text.Html.fromHtml(html).toString();
System.out.println("RECEIVED: "+novo);
if (novo != null) {
if (novo.charAt(0) == '0') {
LeftLightButtonState = false;
LeftLightButton.setTextOff("OFF");
LeftLightButton.setChecked(false);
}
if (novo.charAt(0) == '1') {
LeftLightButtonState = true;
LeftLightButton.setTextOn("ON");
LeftLightButton.setChecked(true);
}
System.out.println("CHEGUEI");
}
}
}
Use different string in the xml files itself. Then based on the state appropriate text will be displayed. You can call setChecked(true/false) to select or unselect the Toggle Button.. It is working fine in my project.
android:textOff="#string/dontshowtraffic"
android:textOn="#string/showtraffic"

Back button press twice before quitting app

How can I configure the back button to be pressed twice before the app exits? I want to trigger
#Override
public void onBackPressed() {
//custom actions
//display toast "press again to quit app"
super.onBackPressed();
}
Try this:
private boolean doubleBackToExitPressedOnce = false;
#Override
protected void onResume() {
super.onResume();
// .... other stuff in my onResume ....
this.doubleBackToExitPressedOnce = false;
}
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show();
}
This snippet handle also the reset state when the activityis resumed
I see this question is a bit old but I though this might help some people looking for an alternative to the answers already given.
This is how I handle backing out of my applications. If someone has a better -- or a Google suggested -- method of accomplishing this I'd like to know.
Edit -- Forgot to mention this is for Android 2.0 and up. For previous versions override onKeyDown(int keyCode, KeyEvent event) and check for keyCode == KeyEvent.KEYCODE_BACK. Here is a good link to check out.
private boolean mIsBackEligible = false;
#Override
public void onBackPressed() {
if (mIsBackEligible) {
super.onBackPressed();
} else {
mIsBackEligible = true;
new Runnable() {
// Spin up new runnable to reset the mIsBackEnabled var after 3 seconds
#Override
public void run() {
CountDownTimer cdt = new CountDownTimer(3000, 3000) {
#Override
public void onTick(long millisUntilFinished) {
// I don't want to do anything onTick
}
#Override
public void onFinish() {
mIsBackEligible = false;
}
}.start();
}
}.run(); // End Runnable()
Toast.makeText(this.getApplicationContext(),
"Press back once more to exit", Toast.LENGTH_SHORT).show();
}
}
You could do what you're asking with a global integer and just count it, if > 2, quit.
But you could take a better (IMO) approach, where you question the user if they would like to quit or not:
private void questionQuit(){
final CharSequence[] items = {"Yes, quit now", "No, cancel and go back"};
builder = new AlertDialog.Builder(mContext);
builder.setCancelable(false);
builder.setTitle("Are you sure you want to quit?");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
switch(item){
case 0:
quit();
break;
case 1:
default:
break;
}
}
}).show();
AlertDialog alert = builder.create();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK :
int i = 0 ;
if(i == 1 )
{
finish();
}
i++;
return true;
}
}
return super.onKeyDown(keyCode, event);
}

Categories