A Timer runs in its own Thread and only the UI Thread is allowed to update visible stuff.
can't seem to update a text view in surface overlay
-
27-11-2021 - |
Question
I have created a Service as seen below.. The service creates a system overlay with a text view that is displaying the time. I have an inlined timer class that is suppose to update the textView with the current time by calling a public method of the Service class.. i know its firing the method and passing the new time via the log i placed in the method but it only seems to change the text in the text view the first time. I assume this has something to do with the surface overlay not redrawing.. anyone have any ideas how i can fix this or if it is even possible:
public class cusNavOverrideService extends Service {
Timer timer;
WindowManager.LayoutParams handleParams;
WindowManager.LayoutParams clockParams;
View screenBlock;
View disableStatusBar;
WindowManager winMgr;
TextView clock;
@Override
public void onCreate() {
winMgr = (WindowManager)getSystemService(WINDOW_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
disableStatusBar = new TableLayout(getApplicationContext());
handleParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FILL_PARENT,
50,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSPARENT);
handleParams.gravity = Gravity.TOP;
handleParams.y = 752;
clockParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FILL_PARENT,
50,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSPARENT);
clockParams.y = 752;
disableStatusBar.setBackgroundResource(R.drawable.cust_bar);
winMgr.addView(disableStatusBar, handleParams);
Typeface tf = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/Futura Bold.otf");
clock = new TextView(getApplicationContext());
clock.setTextColor(Color.BLACK);
clock.setTextSize(30.0f);
clock.setWidth(50);
clock.setTypeface(tf);
clock.setGravity(Gravity.TOP);
clock.setGravity(Gravity.RIGHT);
clock.setPadding(0, 5, 50, 0);
winMgr.addView(clock, clockParams);
timer = new Timer();
uiCheckTask tTask = new uiCheckTask();
tTask.setService(this);
timer.schedule(tTask, 100, 200);
return START_REDELIVER_INTENT;
}
public void updateClock(String newTime){
Log.v("updateClock", "(((((((((((((((((((("+newTime+")))))))))))))))))");
clock.setText(newTime);
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
@Override
public void onDestroy() {
timer.cancel();
winMgr.removeView(disableStatusBar);
//Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
class uiCheckTask extends TimerTask {
cusNavOverrideService myService;
String newTime;
String tempTime;
Time cTime;
String displayTime;
public void setService(cusNavOverrideService service){
myService = service;
cTime= new Time(Time.getCurrentTimezone());
}
public void run() {
try {
cTime.setToNow();
displayTime = cTime.format("%I:%M%P");
if(displayTime.startsWith("0")){
//displayTime ="CHUCK";
newTime = displayTime.substring(1);
}else{
newTime = displayTime;
}
myService.updateClock(newTime);
}
catch(Exception ex)
{
Log.v("WINDOW CHANGE", "exemption:"+ex);
}
}
}
}
Solution
OTHER TIPS
I am having the same problem with my view(s) not disappearing and reappearing. It has to do something with the fact that you (we) added a view using WindowManager.addView(...). Everything is working it is just not updating. Maybe an invalidate?
The solution I used was to create a handler instead of a timerTask