1

I'm new to java and was trying to make a simple android app that does the following:

  • display a window in the main activity
  • every second the value of integer i is increased by 1
  • update the window content to display the value of i every second

for example the window should display the following text:

1st second: "update 1"

2nd second: "update 2"

3rd second: "update 3"

... etc

I learned that using java's ScheduledExecutorService with ScheduleAtFixedRate is better than implementing an infinite loop, so I attempted the following code:

    public class MainActivity extends AppCompatActivity {
    
    public FrameLayout mLayout;
    public WindowManager wm;
    public WindowManager.LayoutParams lp;
    public int i;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // display a window saying "hello"
        wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        mLayout = new FrameLayout(this);
        lp = new WindowManager.LayoutParams();
        lp.format = PixelFormat.TRANSLUCENT;
        lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        LayoutInflater inflater = LayoutInflater.from(this);
        inflater.inflate(R.layout.text_bubble, mLayout);
        ((TextView) mLayout.findViewById(R.id.text)).setText("hello");
        wm.addView(mLayout, lp);

        //creating a scheduled executor service, it runs the method "myTask" at fixed rate of 1 second
        final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                myTask();
            }
        }, 0, 1, TimeUnit.SECONDS);
    }
    
    private void myTask() {
        Log.v(TAG,"Running");

        //Increment i by 1 and update the window layout
        i = i + 1;
        ((TextView) mLayout.findViewById(R.id.text)).setText("update " + i);
        wm.updateViewLayout(mLayout, lp);
    }
}

When I start the app it does display the window as intended, but it doesn't update the number every second, instead it only shows "update 1". I can't tell why as I didn't get any errors. After some trial and error I found that when I remove the last two lines from the myTask method (the lines responsible for updating the text of the window layout):

((TextView) mLayout.findViewById(R.id.text)).setText("update " + i);
wm.updateViewLayout(mLayout, lp);

when I remove these two lines the executor service will function just fine, and I can see that by watching the logged text message "running" popping every second. but when I add those two lines again, it doesn't pop these messages anymore(except for the first second). so what am I doing wrong here? I thought the problem could be about the the way I update the layout maybe. what am I missing here?

Platin78
  • 11
  • 2
  • The UI needs to be updated on the main thread. Try runOnUiThread. – m0skit0 Feb 28 '22 at 18:22
  • wow I didn't even know there was such a thing such as a main UI thread, I tried executing the lines within a runOnUiThread runnable and now it's working. thanks a lot boss much appreciated! – Platin78 Feb 28 '22 at 20:07
  • Does this answer your question? [How do we use runOnUiThread in Android?](https://stackoverflow.com/questions/11140285/how-do-we-use-runonuithread-in-android) – m0skit0 Mar 01 '22 at 12:51

1 Answers1

0

Try this:

Timer timer = new Timer();

timer.schedule(new TimerTask() {
  @Override
  public void run() {
    //Your stuff
  }
}, 0, 1000);

Or this using the scheuldedServiceExecutor:

final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
   //Your stuff
}, 1, 5, TimeUnit.SECONDS);