Scheduled Timer blocking itself - java

I've got following piece of code:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
TextureView textureView = (TextureView) findViewById(R.id.texture);
if (textureView != null) {
try {
Log.i("MainActivity", "Read start");
String str = readQr(textureView.getBitmap());
if (str != null)
Log.i("MainActivity", str);
else Log.i("MainActivity", "No QR Code found.");
} catch (NotFoundException ex) {
Log.i("MainActivity", "No QR Code found.");
} catch (ChecksumException | FormatException e) {
e.printStackTrace();
}
}
}
}, 0, 250);
It should check for a QR code in the TextureView four times a second. The calculation takes a bit less than one second. The problem is, that the timer opens only one thread, which blocks itself => The task gets run only around one time a second.
According to this comment scheduleAtFixedRate should do the trick... But it does not, it behaves exactly like schedule in my situation.
What would be the best option to achieve what I want?
EDIT: I replaced the Timer by a ScheduledExecutorService, as suggested in the comments, but it still results in the exactly same behaviour.
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); // I know it's too much, I just tried using 10 Threads because 4 did still not work.
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
final TextureView textureView = (TextureView) findViewById(R.id.texture);
if (textureView != null) {
try {
Log.i("MainActivity", "Read start");
String str = readQr(textureView.getBitmap());
if (str != null)
Log.i("MainActivity", str);
else Log.i("MainActivity", "No QR Code found.");
Log.i("MainActivity", "Read end");
} catch (NotFoundException ex) {
Log.i("MainActivity", "No QR Code found.");
Log.i("MainActivity", "Read end");
} catch (ChecksumException | FormatException e) {
e.printStackTrace();
Log.i("MainActivity", "Read end");
}
}
}
}, 0, 250, TimeUnit.MILLISECONDS);

A possible solution would be for the timer task to launch a new thread to perform the check, so as long as the new thread launch doesnt take more than 0.25 seconds it would be able to keep up.
The problem is that the actual check is going to overlap, meaning that you may have 3-4 tasks all finding the QR code at the same time. So is that what you want as it may have concurrency issues further down the line.

You want to check the QR code in the background thread and update the ui, then you should use background thread and Handler for updating the UI. It can be done in number of ways. this is one way.
public class FifthActivity extends AppCompatActivity {
Handler uiHandler;
Handler backgroundHandler;
TextView textureView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.collapsing_layout);
textureView = (TextView) findViewById(R.id.textView_fifth);
uiHandler=new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
textureView.setText(msg.getData().getString("msg"));
}
};
HandlerThread thread=new HandlerThread("BackgroundTask");
thread.start();
backgroundHandler=new Handler(thread.getLooper());
backgroundHandler.post(new Runnable() {
#Override
public void run() {
Log.i("FifthActivity", "Read start");
String str = ""+ new Random().nextInt(10);
if (str != null) {
Log.i("FifthActivity", str);
Message message=uiHandler.obtainMessage();
Bundle bundle=new Bundle();
bundle.putString("msg",str);
message.setData(bundle);
uiHandler.sendMessage(message);
// textureView.setText(str);
}
else Log.i("FifthActivity", "No QR Code found.");
backgroundHandler.postDelayed(this,250);
}
});
}
}
You can also use asynctask or Observer pattern Mechanism also

Related

How to run socket code in another threads?

In my application I have adapter and in this adapter I should call socket.
I want call socket in another thread and not call in MainThread.
I write socket code, but I don't know how can I call this in another thread.
My socket code :
mSocket.on("finish", new Emitter.Listener() {
#Override
public void call(final Object... args) {
try {
Constants.currentActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e("socketLogs", args[0] + "");
try {
startTimer();
final FinishResponse finishResponse = new Gson().fromJson(args[0].toString(), FinishResponse.class);
countDownerLayout.setVisibility(View.GONE);
winnerLay.setVisibility(View.VISIBLE);
bidCount.setVisibility(View.GONE);
offerCount.setVisibility(View.GONE);
price.setVisibility(View.GONE);
timeView.setVisibility(View.GONE);
userPic.setVisibility(View.GONE);
winnerLay.setBackgroundColor(ContextCompat.getColor(context, R.color.white));
//if (finishResponse.getRes().getWinnerAvatar() != null && !finishResponse.getRes().getWinnerAvatar().equals("")) {
Glide.with(context)
.load(Constants.SERVER + finishResponse.getRes().getWinnerAvatar())
.placeholder(R.mipmap.ic_launcher)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(User);
/* } else {
User.setImageDrawable(ContextCompat.getDrawable(context, R.mipmap.ic_launcher_round));
}*/
edtUserName.setText(finishResponse.getRes().getWinnerName());
edtUserName.setTextColor(ContextCompat.getColor(context, R.color.black));
txtStartPrice.setText("Sell");
txtStartPrice.setBackgroundColor(ContextCompat.getColor(context, R.color.TextColorGreen));
txtStartPrice.setTextColor(ContextCompat.getColor(context, R.color.white));
try {
String[] splitDate = finishResponse.getRes().getEnd().split(" ");
String[] dateSpliet = splitDate[0].split("-");
TimeUtils timeUtils = new TimeUtils(Integer.parseInt(dateSpliet[0]), Integer.parseInt(dateSpliet[1]), Integer.parseInt(dateSpliet[2]));
txtPrice.setText(splitDate[1] + " " + timeUtils.getIranianDate());
} catch (Exception e) {
}
} catch (JsonSyntaxException e) {
}
}
});
} catch (Exception e) {
}
}
});
I write above code in getView method from Adapter.
But I want write above code in another thread , and not run in MainThread.
How can I do it?
Just create new Thread for this
Runnable runnable = new Runnable() {
#Override
public void run() {
// do stuff
}
};
new Thread(runnable).start();
I would give some recommendations concerning your code. First, it is bad to call Socket in adapter in getView. You should Call it in fragment or Activity (if you don't use MVP or some other architecture).
Next big problem is that you have current activity saved in constants
Constants.currentActivity
It will cause memory leaks, you activity will live even if you close it, and your app will have many problems with such approach.

java update screen in thread

Im writing a script which consists of a thread with a wait. If the thread get executed, it doesn't update the screen. In the script i change a picture to another picture, but it doesn't show it until I press the button again. So the main question is: After setting an different Image Resource, i need to update the screen.
Here is the code:
public void Start(View view) {
Runnable r = new Runnable() {
#Override
public void run() {
int i =0;
while(i<12) {
synchronized (this) {
try {
Setfoto(i);
Thread.sleep(1000);
Log.i(TAG, "Begonnen met loop");
Log.i(TAG, "i = " + i);
i = i +1;
} catch (Exception e) {}
}
}
}
};
Thread buckysThread = new Thread(r);
buckysThread.start();
}
public void Setfoto(int nummer) {
if (nummer == 1) {
een.setImageResource(R.drawable.eerster);
Log.i(TAG, "Foto 1 wordt rood");
} if(nummer ==2) {
twee.setImageResource(R.drawable.eerster);
Log.i(TAG, "Foto 2 wordt rood");
} if(nummer ==3) {
drie.setImageResource(R.drawable.tweer);
Log.i(TAG, "Foto 3 wordt rood");
}
}
You'll need to have some sort of way to run code on the UI thread, which is responsible for updating the contents of the screen and manipulating views.
Activity.runOnUiThread(Runnable) can be called. Any code placed in there will be run on the UI thread.
You can use runOnUiThread, AsyncTask or Thread-Handler to implement your task
Activity.runOnUiThread
runOnUiThread(new Runnable() {
public void run() {
//Do something on UiThread
}
});
Thread-Handler
Communicating with the UI Thread
AsyncTask
AsyncTask Tutorial

how to sleep in for loop until finished loading page android

I am making an app to do something in webview automatically.
I want to make a pause between two lines inside (for-loop) until page finished loading without using Thread.sleep because it freezing my application.
this is my code:
webview.loadUrl("http://**********");
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for(int i=1;i<10;i++){
evaluateJavascript( "document.getElementById('select').value=" + i)
evaluateJavascript("document.getElementById('Search').click();")
//wait until finished loading
while( isloading() ){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
evaluateJavascript( "document.getElementById('any_select').value=5")
.
.
.
.
}
public boolean isloading(){
boolean isloading;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webview.evaluateJavascript("(function() { return document.getElementById(\"Loading\").style.display; })();", new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
if(s.equals("none")){
isloading=false;
}else{
isloading=true;
}
}
});
}
if(isloading=true)return true;
if(isloading=false)return false;
}
If you don't want to use Thread.sleep then the alternative is to use AsyncTask in your application.
You can do your loading task in doInBackground() method of AsyncTask and call it using new AsyncTaskClass.execute();
You can go through it from here : http://developer.android.com/reference/android/os/AsyncTask.html
You can do something similar (instead of AsyncTask):
Edit:
Timer timer = new Timer();
while( isloading() ){
try {
timer.schedule( new TimerTask(){
public void run() {
//
}
}, delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
If you want to achieve, what i understand, that once your second line is called you want to stop there and when after 1000 ms you want to continue. You can do one thing, copy all the code after your second line and put that in run method of below code:
new Handler().postDelayed(new Runnable()
{
#Override
public void run() {
}
}, 1000);
It will execute you code after 1000ms
If you want to execute sequentially actions happening on UIThread and in backgrounds threads you should be looking for the Bolt Library by Parse/Facebook.
It apply Javascript promises to Android application.
You can go through it from here : https://github.com/BoltsFramework/Bolts-Android

Android Timer/Clock

i want a clock/timer that's not insanely fast and force closes like a while loop.
This force closes:
while(loopEnabled == true)
{
//Do stuff
Toast toast Toast.makeText(this, "Hi!", 10000);
toast.show();
}
And so does this:
public void loop()
{
//Do stuff
Toast toast Toast.makeText(this, "Hi!", 10000);
toast.show();
resetLoop();
}
public void resetLoop()
{
Thread.sleep(100);
loop();
}
Any alternatives to stop this? I'm meaning for code to happen rapidly over and over.
Look at Handler especially the postAtTime or postDelayed methods.
For example:
private int mInterval = 1000; // in ms, so 1s here
private Handler mHandler;
#Override
protected void onCreate(Bundle bundle)
{
mHandler = new Handler();
}
Runnable mRepeatingTask = new Runnable()
{
#Override
public void run() {
// do something here
// schedule run again for mTnterval ms from now
mHandler.postDelayed(mRepeatingTask , mInterval);
}
};
void startRepeatingTask()
{
mRepeatingTask.run();
}
void stopTask()
{
mHandler.removeCallbacks(mRepeatingTask);
}
Are you doing this in the UI thread? If so, avoid it as there is a high chance that you will get a Application Not Responding dialog.
In android timers can be implemented using TimerTask and also by Handlers.
Check this link for all sample codes. Async task, handler and timer

Avoid multi-click in image view android

I try to use this code to prevent multi-click in ImageView but it doesn't help.
Boolean isClicked = false;
#Override
public void onClick(View v)
{
if (v == imgClick && !isClicked)
{
//lock the image
isClicked = true;
Log.d(TAG, "button click");
try
{
//I try to do some thing and then release the image view
Thread.sleep(2000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
isClicked = false;
}
}
In the log cat, I can see 5 lines "button click" when I click on ImageView for 5 times as quickly as possible. I can see the log cat print the first line, wait for a while (2 seconds) and then print the next line. I think when I click the ImageView, the fired event is moved to queue in order, isn't it?. So how can I stop that?
I also try to use setEnable() or setClickable() instead of isClicked variable but it doesn't work too.
Just try this working code
Boolean canClick = true; //make global variable
Handler myHandler = new Handler();
#Override
public void onClick(View v)
{
if (canClick)
{
canClick= false; //lock the image
myHandler.postDelayed(mMyRunnable, 2000);
//perform your action here
}
}
/* give some delay..*/
private Runnable mMyRunnable = new Runnable()
{
#Override
public void run()
{
canClick = true;
myHandler.removeMessages(0);
}
};
Instead of sleeping in 2 seconds, I use some task like doSomeThing() method (has accessed UI thread), and I don't know when it completed. So how can I try your way?
//I referred this android link. You can handle thread more efficiently but i hope below code will work for you..
//you try this and
Boolean canClick = true; //make global variable
public void onClick(View v) {
if(canClick){
new DownloadImageTask().execute();
}
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... urls) {
Log.d("MSG","Clicked");
canClick =false;
//perform your long operation here
return null;
}
protected void onPostExecute(Bitmap result) {
canClick =true;
}
}
You could keep track of the last consumed click upon your View, and based on it either perform the necessary actions, or simply return:
private long calcTime;
private boolean isClickedLately(final long millisToWait)
{
if (System.currentTimeMillis() - calcTime < millisToWait)
return true;
return false;
}
#Override
public void onClick(View v)
{
if (isClickedLately(2000))
return;
calcTime = System.currentTimeMillis();
Log.d(TAG, "consuming button click");
// perform the necessary actions
}
With the millisToWait parameter you can adjust the threshold of "waiting", but if you know that you want to wait exactly 2 seconds between two consecutive clicks, you can eliminate it.
This way you don't have to deal with Threads, which is good, since it's not a great idea to make the gui thread wait.

Categories