I'm coding a music app with buttons. I want to make music sound while a button is pressed but stop it when it's released. Also I want to play the music in a constant loop without separation between loop times.
Now when I press the button music starts to play but when I release the button it stills playing untill the end of the file.
This is the code:
#Override
public boolean onTouch(View v, MotionEvent event) {
MediaPlayer do2n = MediaPlayer.create(this, R.raw.do_leg);
if(event.getAction() == MotionEvent.ACTION_DOWN) {
if(v.getId()==R.id.dor){
do2n.start();
}
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if(v.getId()==R.id.dor){
if (do2n != null)
do2n.release();
}
}
return true;
}
Well, you have actually created 2 instances of MediaPlayer since onTouch is called twice: once for key down and once for key up. So the first time you're creating the player and then you lose the reference. The second time onTouch is called, for ACTION_UP you're creating a new MediaPlayer object, but that object is a different one than the previous created with ACTION_DOWN so calling stop on this newly created object has no effect.
So you could instantiate the player as a class variable. Something like below:
private MediaPlayer do2n;
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (v.getId() == R.id.dor) {
do2n = MediaPlayer.create(this, R.raw.do_leg);
do2n.start();
}
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (v.getId() == R.id.dor) {
if (do2n != null) {
do2n.stop();
do2n.release();
do2n = null;
}
}
}
return true;
}
#Override
protected void onDestroy() {
super.onDestroy();
/**
* The activity may be destroyed if you receive a long phone call while
* keeping the button pressed so it's safe to do this
*/
if (do2n != null) {
do2n.stop();
do2n.release();
}
}
Related
how can i detect if volume up and down buttons are pressed simultaneously for certain period of time to perform specific task on android. I'm currently using java to develop an application which increment the count on pressing volume up and down button together for some period of time.
if(keycode == KeyEvent.KEYCODE_VOLUME_DOWN && keycode == KeyEvent.KEYCODE_VOLUME_UP) {
// Two buttons pressed, call your function
count++;
String num = String.valueOf(count);
number.setText(num);
Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_SHORT).show();
}
I tried this code but it didn't work
I also used boolean
while(keycode == KeyEvent.KEYCODE_VOLUME_DOWN || keycode == KeyEvent.KEYCODE_VOLUME_UP){
if (keycode == KeyEvent.KEYCODE_VOLUME_DOWN){
down = true;
if(keycode == KeyEvent.KEYCODE_VOLUME_UP){
up = true;
if(up && down) {
// Two buttons pressed, call your function
Toast.makeText(getApplicationContext(), "Hello",
Toast.LENGTH_SHORT).show();
}
}
}
}
Try this, it will work :
ArrayList<Integer> pressedkeys = new ArrayList<>();
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
pressedkeys.add(keyCode);
if(event.isLongPress())
if(pressedkeys.contains(24) && pressedkeys.contains(25)) {
//Do Something;
}
return (true or false);
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
pressedkeys.removeAll(Collections.singleton(keyCode));
return (true or false);
}
Return true if you handled the event and does not want anything else to happen or false if you want to allow the event to be handled by the next receiver.
Note : Please feel free to improve my answer...
You can also checkout this : Android 2 keys at a time
I want to implement a KioskMode, I'm targeting only Android L, since this is a very specific App.
I already went through the process of setting my App as DeviceAdmin, and
DevicePolicyManager.isLockTaskPermitted(this.getPackageName()) already returns true.
I then start a LockTask via startLockTask().
Everything is fine, but when I hold down the backbutton, the app still exits the kiosk mode.
I have overridden onKeyPress to show a custom Dialog for unlocking the app, but this does not hinder android to automatically exit my lock task if the user holds down back.
I don't really know what to do at the moment and would be thankful for every input.
I now have overridden
#Override
public boolean onKeyDown(int KeyCode, KeyEvent event)
{
if(KeyCode == KeyEvent.KEYCODE_BACK)
{
BackDownButtonPressed = true;
if(VolDownPressed)
showTaskLockDialog();
return true;
}
else if(KeyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
VolDownPressed = true;
if(BackDownButtonPressed)
showTaskLockDialog();
return true;
}
return super.onKeyDown(KeyCode, event);
}
#Override
public boolean onKeyUp(int KeyCode, KeyEvent event) {
if(KeyCode == KeyEvent.KEYCODE_BACK)
{
BackDownButtonPressed = false;
return true;
}
else if(KeyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
VolDownPressed = false;
return true;
}
return super.onKeyUp(KeyCode, event);
}
#Override
public void onBackPressed()
{
return;
}
#Override
public boolean onNavigateUp() {
return true;
}
#Override
public boolean dispatchKeyEvent (KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
return true;
}
return true;
}
#Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//do something or nothing in your case
return true;
}
return super.onKeyLongPress(keyCode, event);
}
For the record, I am using a Samsung SM-T700 Tablet with Cyanogenmod CM12.1
Just to close this topic..
I couldn't figure out a perfect solution to this day. My current workaround is receiving an event if the user leaves the kiosk mode and just entering the kiosk mode again.
Sadly this leaves the user with 2 toasts saying "screen unpinned" and "screen pinned", which is unfortunate. But this satisfies my current needs.
Perhaps you need to override onKeyLongPress
#Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//do something or nothing in your case
return true
}
return super.onKeyLongPress(keyCode, event);
}
Not sure if it's helpful at all, but I wrote a blog about setting Kiosk Mode here:
http://www.sureshjoshi.com/mobile/android-kiosk-mode-without-root/
And also wrote sample code for it here:
https://github.com/sureshjoshi/android-kiosk-example
Not sure if you see any major differences between your code and mine, but I just tried to do a long press on a Samsung Galaxy Tab 4 running Android 5.0, and it won't exit the app.
Could it be something with rooting with Cyanogen?
If you don't have this in your code, perhaps add it in and check out if you see any problems:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Remove title bar and notification bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
ComponentName deviceAdmin = new ComponentName(this, AdminReceiver.class);
mDpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
if (!mDpm.isAdminActive(deviceAdmin)) {
Toast.makeText(this, getString(R.string.not_device_admin), Toast.LENGTH_SHORT).show();
}
if (mDpm.isDeviceOwnerApp(getPackageName())) {
mDpm.setLockTaskPackages(deviceAdmin, new String[]{getPackageName()});
} else {
Toast.makeText(this, getString(R.string.not_device_owner), Toast.LENGTH_SHORT).show();
}
mDecorView = getWindow().getDecorView();
}
and
protected void enableKioskMode(boolean enabled) {
try {
if (enabled) {
if (mDpm.isLockTaskPermitted(this.getPackageName())) {
startLockTask();
mIsKioskEnabled = true;
} else {
Toast.makeText(this, getString(R.string.kiosk_not_permitted), Toast.LENGTH_SHORT).show();
}
} else {
stopLockTask();
mIsKioskEnabled = false;
}
} catch (Exception e) {
// TODO: Log and handle appropriately
}
}
I have the same problem: How to stop "holding the back button" from escaping "Lock Task mode" on Android 6+
The issue only occurs on my Android 7 tablet.
Running the app on my Android 6 tablet fixed the problem.
Could you add some code to illustrate your current work-around?
I'm trying to set my own long click listener on Unlock button. Whenever I press the Unlock button it summarize duration and I can unlock permanently clicking.
Unlock.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(final View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Unlock.setText("Press to unlock");
isLongPress = true;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (isLongPress) {
Unlock();
}
}
}, longClickDuration); //amount of time of long click
} else if (event.getAction() == MotionEvent.ACTION_UP) {
Unlock.setText("Unlock");
isLongPress = false;
}
return true;
}
});
}catch (Exception e) {
// TODO: handle exception
}
}
If you want to just handle long clicks consider using the following code:
Unlock.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
your code
}
});
But if the Unlock(); should be invoked after a certain (customizable) amount of time, you should measure this time in MotionEvent.ACTION_UP handler. As #Attaullah Khan said, use SystemClock.elapsedRealtime() system timer to correctly count number of milliseconds at two moments (when button was pressed and released) and if the time is greater than longClickDuration then invoke Unlock
The handler.postDelayed that you call in MotionEvent.ACTION_DOWN handler just invokes a check of pressed state after longClickDuration interval and if your button gets suddenly pressed at that moment, the verification passes that is not correct
I'm trying to detect when "Go" is pressed on the android Keyboard (the last key on the bottom right).
My code works in the emulator and on my Nexus 5, but doesn't on some other Android devices.
What am I doing wrong?
editTextMain.setImeActionLabel("Go", KeyEvent.KEYCODE_ENTER);
editTextMain.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if(i==KeyEvent.KEYCODE_ENTER)
{
Intent intent = new Intent(thisActivity, ActivityRisultati.class);
startActivity(intent);
return true;
}
}
}
Try this
editText = (EditText) findViewById(R.id.edit_text);
editText.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// do your stuff here
}
return false;
}
});
I have some code in my app which detects when any key which sends the KEYCODE_ENTER value is pressed. It detects both the Enter and Done keys on a Motorola Droid 3 slide-out keyboard. Here's my code:
private OnKeyListener enterKeyListener = new OnKeyListener()
{
public boolean onKey(View v, int k, KeyEvent e)
{
/*
* "Enter" or "Done" key was pressed
*/
if( (e.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (e.getAction() == KeyEvent.ACTION_UP) )
{
//
// Do some stuff ...
//
return true;
}
return false;
}
};
Note the additional check for KeyEvent.ACTION_UP. You might need that on some devices in order to prevent the listener from firing as soon as the button is pressed, and repeatedly if the button is held down. In my case, I only wanted it to take an action if the key had been pressed and then released.
Hope this helps.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
public void onClick(View v)
{
if (v.getId()== R.id.but1 && v.getId()== R.id.but2)
{
Intent intent=new Intent(First.this,Second.class);
startActivity(intent);
}
}
There isn't such event that can be associated to two controls. event handlers only associated to one control and that is different than assigning the same listener to two button. listener will receive a call from every button separately.
Also, listeners will never be triggered together because both run in the same thread (The UI thread). It's impossible to catch on click event for both controls at some moment. one listener will be triggered and then the other. Even if we assumed that the user managed to click those together at the same millisecond or so in the perfect world. Any way who can decide that when they are clicked at same millisecond they considered to be clicked to gather! why not same nanosecond. and why not the same hour :)
Ok, it's enough explaining the click event.
What we need is the touch event and it can be played as follow (the code will also explain how the touch event work):
Activity Class Members:
public boolean b1Down = false, b2Down = false;
onCreate Method Code:
Button b1 = (Button)findViewById(R.id.button1);
Button b2 = (Button)findViewById(R.id.button2);
b1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
boolean consume = false;
if (event.getAction() == MotionEvent.ACTION_UP)
{
b1Down = false;
}
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
b1Down = true;
if (b2Down)
{
// both are clicked now //
Toast.makeText(MainActivity.this, "Both are clicked now!", Toast.LENGTH_SHORT).show();
}
consume = true;
}
return consume;
}
});
b2.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
boolean consume = false;
if (event.getAction() == MotionEvent.ACTION_UP)
{
b2Down = false;
}
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
b2Down = true;
if (b1Down)
{
// both are clicked now //
Toast.makeText(MainActivity.this, "Both are clicked now!", Toast.LENGTH_SHORT).show();
}
consume = true;
}
return consume;
}
});