Timers accuracy - android

I am using this library to establish a connection and data transfer between two android devices. what i want to do is: one phone send the same message every 2 seconds, everytime the receiver reads the message, it starts some work..
I tried doing that with Timers and TimerTasks, but it is not synchronized at all. i get weird different delays.
public void onClick(View v){
new Timer().schedule(new TimerTask()
{
public void run()
{
bt.send("Start");//////////////////////////////////////////////////////
Log.i("time", "data sent "+System.nanoTime());
}
try {
Thread.currentThread();
Thread.sleep(50, 0);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s.playSound();
//
}
}
, 0, 3000);
and also sleep() is not a good way to produce delays, because sometimes its interrupted.
Is there any other way to do that?

Related

Android - two actions in app at the same time

I am developing app and I need that my app will be doing two actions at the same time. For example - I can drag marker and the map will be scrolling at the same time.
I tried to update map while dragging marker, everything would be okay, except thing that when thread starts, maps starts scrolling continuously and I cand do anything more. Here is the code, I call it in onCreate() method. I tried to do Runnable and AsyncTask and the results were the same. Any suggestions?
private void update() {
new Thread() {
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
while (drag)
mMap.animateCamera(CameraUpdateFactory.scrollBy(10, 0), 2, null);
}
});
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
You don't have the code to interrupt your thread. That's why your map keep scrolling. Try to use drag event to drive this animation, and add some code to terminate the thread at some point.

Puzzle: Bluetooth data send interval shortened by half after each reconnect

I modified the standard Bluetoothchat example to send 4 bytes of data at a time to a bluetooth device every half a second. It works fine if I start the App fresh. However, there is a problem if I reconnect as follows:
While Bluetooth is connected, I click the connect button again on the menu and select the same device. This disconnects the bluetooth (not sure whether this is the right procedure to disconnect). Then, I connect again by selecting the device, and it will be reconnected. After reconnection, a very strange problem appears: instead of sending the data every half a second, it will send the data every quarter a second. If I go through the process again and reconnect, the time interval will become even shorter. It gets to a point that the bluetooth device on the receiving end can't keep up with the data. At this point, the only way out is to kill the app and restart again. Then everything becomes normal, till next time I try to reconnect again.
I have tried different things but nothing appear to fix this. For example, I made sure the thread sending the data is killed when disconnected so no multiple threads are sending the data. I was wondering whether the baud rate changed when reconnected, but then why would the baud rate affect the Thread.sleep(500); statement (which is responsible for controlling the half a second data send). Any help would be greatly appreciated.
Here is the code, the SendClass is created under the MainActivity:
class SendClass implements Runnable {
public void run() {
bytearr[0]=0;bytearr[1]=0;bytearr[2]=0;bytearr[3]=0;
while (!Thread.currentThread().isInterrupted()) {
if (mChatService==null || mChatService.getState()
!=BluetoothChatService.STATE_CONNECTED) {
continue;
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mChatService.write(bytearr);
}
}//end of run
}//end of runnable
Then under STATE_CONNECTED:
case BluetoothChatService.STATE_CONNECTED:
setStatus(getString(R.string.title_connected_to,mConnectedDeviceName));
/*
if(sendingThread!=null){
//sendingThread.stop();
sendingThread.interrupt();
if(D) Log.i(TAG, "after sendingThread");
sendingThread = null;
}*/
sendingThread = new Thread(new SendClass());
sendingThread.start();
break;
As you can see, I tried to kill the thread before creating a new one but that didn't make any difference. Any suggestions?
You are creating a thread that never actually stops, even after you create a new thread and assign to the same variable that particular thread wont stop running.
You need to make sure that the thread will stop after it disconnects.
Here is my suggestion
Change your SendClass to:
class SendClass implements Runnable {
private boolean stopped = false;
public void setStopped(boolean s){
this.stopped = s;
}
public void run() {
bytearr[0]=0;bytearr[1]=0;bytearr[2]=0;bytearr[3]=0;
while (!Thread.currentThread().isInterrupted() && !stopped) {
if (mChatService==null || mChatService.getState() !=BluetoothChatService.STATE_CONNECTED) {
continue;
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mChatService.write(bytearr);
}
}//end of run
}//end of runnable
Then when you start your thread keep the reference to the Runnable so you can call the setStopped(true); like this
SendClass sc = new SendClass();
sendingThread = new Thread(sc);
sendingThread.start();
When you disconnect the bluetooth dont forget to call sc.setStopped(true); so your thread will finish by not going into the while.

Simple Networking using Datagram in Android

I am trying to make a simple app. Where user sees one edittext .. enters some text in it.. and then press send... then the server on laptop receives that message.
Now the NetworkOnMainThread exception is giving me Headaches......the app works perfectly for 2.3.3 because there was no such thing as NetworkOnMainThread Exception that time.
Having searched a lot .. Two solutions are
Making new thread for networking OR
AsyncTask.
I tried both without any results.
Try 1: With Separate Thread:
Now what I could understand is that I had to start a separate thread. Ok. I did.
Following is my client side code.
EditText e ;
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
e= (EditText) findViewById(R.id.editText1);
tv = (TextView) findViewById(R.id.textView1);
Thread startNetworking = new Thread(new NetworkThread());
startNetworking.start();
}
public void sendMessage(View v){
if(NetworkThread.sendToClient(e.getText().toString()))
tv.setText("Status : Successful");
else
tv.setText("Status : Unsuccessful");
}
sendMessage is onClick function for my send button. I have another JAVA file NetworkThread.java....
Here is a code for that :
public class NetworkThread implements Runnable{
static DatagramSocket socket;
static InetAddress add;
public void run() {
try {
socket = new DatagramSocket();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
add = InetAddress.getByName("192.168.1.12");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static boolean sendToClient(String message){
DatagramPacket p = new DatagramPacket(message.getBytes(),message.getBytes().length,add,4444);
try {
socket.send(p);
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
}
This is still doesn't work. I first want to exhaust this first try then I will move onto asking here about AsyncTask and what I have tried. So for time being please help me achieve this simple task of sending and receiving a string.
Unfortunately, having sendToClient() defined in the same class as NetworkThread doesn't mean that it will run on your network-specific thread. The sendToClient() method will still run on your main (UI) thread because it's being called from your onClick() method. UI callbacks, such as onClick(), are always processed on the UI thread.
I would recommend using an AsyncTask as it enables you to send arbitrary data (such as your message parameter) to the background/network thread before it executes. Continuing to use Runnable and Thread will require extra machinery to synchronize the execution of your UI and network threads, and these challenges are handled behind the scenes by AsyncTask.

Changing postdelayed method every entrance

I have to change ttyS1 port's baudrate every second. So i need to wake-up remote machine on 9600 Bauds and after communicate with it on 19200 Bauds. But there is a time limit between wake-up signal and real data communication. I use Handler&Thread for this trick.
I done it and seems okay with Handler&Thread. I toggled postdelayed every entrance for 1 milliseconds and 500 milliseconds. But it works bad. Sometimes 1 milliseconds task takes almost 10-15 milliseconds.
Also i noticed that when i add "runOnUiThread" with some UI update, result goes worst like 30milliseconds.
Note: I need to send Wake-up signal everytime not just one time.
Any idea?
public void serial_query(){
try {
Runnable cookimageupdate = new Runnable(){
public void run(){
try {
if (mOutputStream != null) {
mSerialPort.close();
if (mLAP==0) //First LAP is used to HOLTEK Wake-Up. Second one is real data.
{mLAP=1; mSerialPort=new SerialPort(new File("/dev/ttyS1"), 9600, 0); mBufferbuf = (byte)0x00; mOutputStream.write(mBufferbuf);}
else {mLAP=0; mSerialPort=new SerialPort(new File("/dev/ttyS1"), 19200, 0); mOutputStream.write(mBuffer);}
} else {
return;
}
} catch (IOException e) {
e.printStackTrace();
return;
}
try{
runOnUiThread(new Runnable() {
public void run() {
//meat_temp.setText(_meatprobe_temp.toString());
if (_pt1000_status==1) {pt_status.setText(" PT1000 open-circuit");}
else if (_pt1000_status==2){pt_status.setText(" PT1000 short-circuit");}
else if (_pt1000_status==0){pt_status.setText(" -");}
}
});
}
catch (Exception e)
{
e.getLocalizedMessage();
}
if (mLAP==1)
{handler_serial.postDelayed(this, 1);}
else {handler_serial.postDelayed(this, 500);}
}
};
handler_serial.postDelayed(cookimageupdate, 50); //start with 50mSec. delay
}
catch(Exception e){
e.printStackTrace();
return;
}
};
1 millisecond is too short a time delay to post a delayed runnable. Most handlers take more time than that to process your message.
For such low delays you would be better off using
Thread.sleep().

How to use scheduleAtFixedRate for executing in each second

in the below code send() function is executing many times in a second,i want to execute send() once in a second,how i change the code
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
try {
send();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},
1000,
1000);
send function is given below
void send() throws Exception, IOException
{
s=new Socket("10.0.2.2",4200);
r=new PrintWriter(s.getOutputStream());
while(true)
{
Log.e("msg","hi send\n");
r.print("hai");
}
}
Logcat output is given below
I replaced timers with Runnables/Handlers recently, it's much easier
//declare at top of your activity
private Handler h = new Handler();
private Runnable myRunnable = new Runnable() {
public void run() {
//do stuff
//run again in one second
h.postDelayed(myRunnable, 1000);
}
};
//trigger the runnable somewhere in your code e.g. onClickHander or onCreate etc
h.postDelayed(myRunnable, 1000);
It happened for me when I used a TaskTimer and the phone got into sleep mode. I think it is related to TimerTask using Thread.sleep() to provide the timing. This relies on uptimeMillis() which according to documentation - 'is counted in milliseconds since the system was booted. This clock stops when the system enters deep sleep (CPU off, display dark, device waiting for external input), but is not affected by clock scaling, idle, or other power saving mechanisms. This is the basis for most interval timing such as Thread.sleep(millls)'
Solution would be either to use AlarmManager or WakeLocks.
an easier approach would look like this:
new Thread() {
public void run() {
while(true) {
send();
try{
Thread.sleep(1000); // pauses for 1 second
catch(Exception e) {}
}
}
}.start();

Categories

Resources