I want to send data via bluetooth while a button is pressed. I am using an ontouchlistener. After the button down event happens the data transfer is started but when the button up event happens the transfer is not stopped immediately. At the bluetooth receiver side I see a lot of data incoming still after the button is released for a specific amount of time.
I tried to solve this issue with an flag which is evaluate in a while statement in the called methode. But this brings me to the above descriped issue.
Then I tried to solve this via an additional thread which is killed during the button up event. But the result did not changed.
Here is my code. Maybe somebody can help me.
mButtonMoveRight.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
moveRight p = new moveRight();
Thread th = new Thread(p);
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
pressed_right = true;
th.start();
break;
case MotionEvent.ACTION_UP:
pressed_right = false;
th.interrupt();
break;
}
return false;
}
});
private class moveRight implements Runnable
{
#Override
public void run()
{
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
while (pressed_right == true) {
if (btSocket != null) {
try {
btSocket.getOutputStream().write("r".toString().getBytes());
} catch (IOException e) {
msg("Error");
}
}
}
}
}
Related
I need to make an app which, when a button is pressed, a character is sent to Arduino via Bluetooth with a delay of 50ms. I'm new to Android and surfing on the internet I found this solution:
base_destra.setOnHoverListener(new View.OnHoverListener() {
#Override
public boolean onHover(View v, MotionEvent event) {
while(event.getAction() == MotionEvent.ACTION_DOWN){
sendData("d");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(event.getAction() == MotionEvent.ACTION_UP){
sendData("10");
}
return false;
}
});
Where sendData is this:
private void sendData(String data){
if(OutStream == null){
return;
}
byte[] comando = data.getBytes();
try {
OutStream.write(comando);
}
catch (IOException e){
Toast.makeText(getBaseContext(),"Errore: comando non mandato",Toast.LENGTH_SHORT).show();
}
}
I saw a tutorial on YouTube but although I copy-pasted the code shown, the app doesn't send anything.
PS: Arduino and the phone are correctly connected.
PPS: sorry for my bad English.
You can use a Timer. In the toggle button onClick method you can call timedDataSender() and in the button off method you can set shouldCancel boolean variable to true and the sending task should be finished. Here is a sample code:
/* A sendTimer is used to periodically send data */
private Timer sendTimer;
private Boolean shouldCancel = false;
private void timedDataSender(){
TimerTask task = new TimerTask() {
public void run() {
runOnUiThread(new Runnable(){
#Override
public void run() {
sendData("10");
}
});
if(shouldCancel)
cancel();
}
};
sendTimer = new Timer("Timer");
/* TimerTask, startDelay, period */
sendTimer.scheduleAtFixedRate(task,0,50);
}
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 using a rooted tabled with an USB port in host mode to read the value of an xbox-controller-joystick (with onJoystickMotion).
Now, I also want to track the buttons keycode_button_a, keycode_button_b, keycode_button_x, keycode_button_y and keycode_button_select. The tracking is working, but pressing these buttons will hide the activity.
Is there any way to disable android hiding an activity on this keycode_button_... events?
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
InputDeviceState state = getInputDeviceState(event);
if (state != null) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
if (state.onKeyDown(event)) {
//Do my thing
}
break;
case KeyEvent.ACTION_UP:
if (state.onKeyUp(event)) {
//Do my thing
}
break;
}
return true;
}
return super.dispatchKeyEvent(event);
}
Yeah :D
I want to lower (or upper) my media volume in my application when an "OnLongClickEvent" is detected.
Here my sources :
buttongauche.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
playSound(R.raw.volumevoixdiminue);
audio.adjustStreamVolume(AudioManager.STREAM_MUSIC,AudioManager.ADJUST_LOWER,AudioManager.FLAG_SHOW_UI);
return true;
}
});
Actually, it's work : when I do a longClick on my "buttongauche", the volume is decreased by 1.
Now I would like to know how could I do if I want to lower the sound continuously (for example, decrease sound by 1 every 2 seconde when the button is down).
My button "buttongauche" has already an "onClickEvent", who do other things (change the index of a menu).
Thanks
Declare field boolean touching = false; that says whether or not you are touching the button and use OnTouchListener to change it. When you start touching also start volumeThread that lowers the volume every 1 second, and dies when you stop touching.
buttongauche.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touching = true;
Thread volumeThread = new Thread() {
public void run() {
while (touching) {
audio.adjustStreamVolume(
AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER,
AudioManager.FLAG_SHOW_UI);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
volumeThread.start();
break;
case MotionEvent.ACTION_UP:
touching = false;
break;
}
return false;
}
});
I'm having a hard time working with this.
I have a Media player, and I can play, pause, stop, play again after pause, stop... whatever.
Now I wanted to have a SeekBar to give a visual component. My problem is:
When I start the player for the first time everything works well. Music plays, and seek bar updates. also works when I pause.
Now, if I stop the player and start it again, the player starts, the run() method executes, but the seekbar doesn't update, and soon the app gives a not responging error.
What am I missing here?
The run method is an implementation from the Runnable interface, and with a simple log, I can see it's being executed, even after the stop/play case. The only thing that seems not to be working is the seek.setProgress(...).
some help, please? :)
Here's my code:
public class MediaPlayerTestingActivity extends Activity
implements OnClickListener, OnPreparedListener, Runnable {
private MediaPlayer mp;
private boolean paused = false;
private SeekBar seek;
private boolean threadStarted = false;;
private Thread thread = new Thread(this);
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
seek = (SeekBar)findViewById(R.id.seek);
mp = new MediaPlayer();
Button start = (Button)findViewById(R.id.start);
start.setOnClickListener(this);
Button pause = (Button)findViewById(R.id.pause);
pause.setOnClickListener(this);
Button stop = (Button)findViewById(R.id.stop);
stop.setOnClickListener(this);
}
//click handlers
public void onClick(View v)
{
int buttonId = v.getId();
switch (buttonId)
{
case R.id.start:
if(mp != null)
{
if(!mp.isPlaying() && !paused)
prepareTostartPlayer();
else
mp.start(); //if it was just paused
}
else
{
mp = new MediaPlayer();
prepareTostartPlayer();
}
break;
case R.id.pause:
if(mp.!= null && mp.isPlaying())
{
mp.pause();
paused = true;
}
break;
case R.id.stop:
if(mp != null && mp.isPlaying())
{
mp.stop();
mp.release();
mp = null;
}
break;
default:
break;
}
}
//When the player is ready to play
public void onPrepared(MediaPlayer arg0)
{
seek.setMax(mp.getDuration());
mp.start();
if(!threadStarted)
thread.start();
else
thread.run();
}
//Method to prepare to start the player
private void prepareTostartPlayer()
{
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mp.setDataSource("http://feedproxy.google.com/~r/rc-cadernetadecromos/~3/JH1kfZCmP3M/cdc_190112_2.mp3");
mp.prepareAsync();
mp.setOnPreparedListener(this);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void run()
{
threadStarted = true;
int current = 0;
while(mp != null && current < mp.getDuration())
{
try {
current = mp.getCurrentPosition();
seek.setProgress(current);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I see three issues here:
First, this part:
public void onPrepared(MediaPlayer arg0)
{
seek.setMax(mp.getDuration());
mp.start();
if(!threadStarted)
thread.start();
else
thread.run();
}
The first time your run the thread you set threadStarted to true in the thread code, but you never set it back to false when the thread finishes. So after the first run it will be true forever and thus the else above will always execute, running the player code sequentially and thus blocking your user interface.
Second, you are updating the user interface (the SeekBar) from a different thread than the UI thread. See this related question for how to correctly update the UI in this case: Update UI from Thread
Third, this may be just a recommendation, but since your threadStarted variable is modified between threads, it's better to declare it volatile to prevent some optimizations from breaking your code:
private volatile boolean threadStarted = false;
According to my experience and what is written in docs, threads in Android work only in purely algorythmic parts of a prog. Any try to use them in activities, or anything connected to UI, goes to error. This way it simply won't work. Never can you repair it!
Use AsyncTask (or child Activity/Fragment for greater things) instead.