1

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);
Community
  • 1
  • 1
Benni
  • 778
  • 8
  • 22

2 Answers2

0

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.

Theresa Forster
  • 1,914
  • 3
  • 19
  • 35
  • ...which is not a problem, because although the results are a bit delayed, I still get my results four times a second, which is what I want to achieve. – Benni Oct 17 '16 at 13:34
0

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

Kona Suresh
  • 1,836
  • 1
  • 15
  • 25
  • Sorry for the late reply. This one does exactly the same as my solution since it does not scan the picture until the previous scan is completed. (```backgroundHandler.postDelayed``` gets called after the previous scan is finished. I tried putting it to the beginning, which still has no effect at all.) – Benni Oct 19 '16 at 13:10
  • yes because you scan the something continuously(it is more faster and scanning in milli seconds), So why you give the 250 ms time. you can try with 20 ms tim,then it may be helpful. The above code call only after 250 ms. – Kona Suresh Oct 20 '16 at 07:14
  • I want to run the scan every 250ms, regardless if another scan process is already running or not. What your code does is to wait for the scan to complete, wait 250ms and run the scan again. If the scanning takes 1000ms, I've got a delay of not 250 but 1250ms, which is a huge difference. Even if I would do ```backgroundHandler.postDelayed(this, 0);```, it would have a 1000ms + 0ms = 1000ms delay and not 250ms. – Benni Oct 20 '16 at 14:23