I have a problem with a quite simple Android app that I'm deveolping. It's something like a football score board. The activity consists of 3 fragments (2 for the team goals and 1 for the timer) and I have a service to perform the countdown. It seems to work, but when I rotate the screen, the countdown continue but it doesn't update my textview (called "timer"). I'm posting the code of the fragment, the activity and the service. I'm sorry if sometimes the code is a bit messy.
public class BoardActivity extends FragmentActivity implements BoardActivityCallback{
public static final String TAG = "BoardActivity";
public static final boolean D = true;
public static final String TEAM_NAME1 = "TEAM_NAME1";
public static final String TEAM_SCORE1 = "TEAM_SCORE1";
public static final String TEAM_NAME2 = "TEAM_NAME2";
public static final String TEAM_SCORE2 = "TEAM_SCORE2";
public static final String HALF_TIME = "HALF_TIME";
public static final String HALF_NUMBER = "HALF_NUMBER";
public static final String OUT_TIME = "OUT_TIME";
public static final String ROBOTS_NUMBER = "ROBOTS_NUMBER";
public static final int CREATE_AND_START_TIMER = 0;
public static final int GET_ACTIVITY_MESSENGER = 55;
private TeamFragment teamFragment1;
private TeamFragment teamFragment2;
private TimerFragment timerFragment;
private boolean isPlaying;
//private TimeService timeService;
private boolean isTimeServiceBound;
private Messenger fromService = new Messenger(new MessagesFromTimeServiceHandler());
private Messenger toService;
private Message message;
private ServiceConnection timeServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//timeService = ((TimeService.ServiceBinder)service).getService();
//Toast.makeText(BoardActivity.this, "Service connected", Toast.LENGTH_SHORT).show();
toService = new Messenger(service);
Message msg = new Message();
msg.what = GET_ACTIVITY_MESSENGER;
try {
toService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//timeService = null;
//Toast.makeText(BoardActivity.this, "Service disconnected", Toast.LENGTH_SHORT).show();
toService = null;
}
};
private void doBindTimeService(){
Intent bindIntet = new Intent(BoardActivity.this,TimeService.class);
//bindIntet.putExtra("Messenger", fromService);
//bindIntet.putExtra("Halftime",getIntent().getStringExtra(HALF_TIME));
bindService(bindIntet, timeServiceConnection, Context.BIND_AUTO_CREATE);
//bindService(new Intent(BoardActivity.this,TimeService.class), timeServiceConnection, Context.BIND_AUTO_CREATE);
isTimeServiceBound = true;
}
private void doUnbindTimeService(){
if(isTimeServiceBound){
unbindService(timeServiceConnection);
isTimeServiceBound = false;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.board);
if(D) Log.d(TAG,"--- onCreate ---");
teamFragment1 = (TeamFragment) getSupportFragmentManager().findFragmentById(R.id.teamFragment1);
teamFragment2 = (TeamFragment) getSupportFragmentManager().findFragmentById(R.id.teamFragment2);
timerFragment = (TimerFragment) getSupportFragmentManager().findFragmentById(R.id.timerFragment);
Intent callingIntent = getIntent();
if(teamFragment1 != null && teamFragment2 != null && timerFragment != null && callingIntent != null){
teamFragment1.setColor(getResources().getColor(R.color.yellow));
teamFragment2.setColor(getResources().getColor(R.color.blue));
teamFragment1.setName(callingIntent.getStringExtra(TEAM_NAME1));
teamFragment2.setName(callingIntent.getStringExtra(TEAM_NAME2));
teamFragment1.setOutTime(callingIntent.getStringExtra(OUT_TIME));
teamFragment2.setOutTime(callingIntent.getStringExtra(OUT_TIME));
// timerFragment.setHalfTime(callingIntent.getStringExtra(HALF_TIME));
// timerFragment.setHalfNumber(callingIntent.getStringExtra(HALF_NUMBER));
try{
teamFragment1.setScore(Integer.parseInt(callingIntent.getStringExtra(TEAM_SCORE1)));
teamFragment2.setScore(Integer.parseInt(callingIntent.getStringExtra(TEAM_SCORE2)));
String robotsNumberString = callingIntent.getStringExtra(ROBOTS_NUMBER);
int robotsNumber = Integer.parseInt(robotsNumberString.substring(0, robotsNumberString.indexOf(' ')));
teamFragment1.setRobotsNumber(robotsNumber);
teamFragment2.setRobotsNumber(robotsNumber);
}catch(NumberFormatException nfe){
Log.e(TAG,nfe.getMessage());
}
}
}
@Override
protected void onStart() {
super.onStart();
doBindTimeService();
if(D) Log.d(TAG,"--- onStart ---");
}
@Override
protected void onPause() {
super.onPause();
if(D) Log.d(TAG,"--- onPause ---");
}
@Override
protected void onResume() {
super.onResume();
if(D) Log.d(TAG,"--- onResume ---");
}
@Override
protected void onStop() {
super.onStop();
doUnbindTimeService();
if(D) Log.d(TAG,"--- onStop ---");
}
@Override
protected void onDestroy() {
super.onDestroy();
if(D) Log.d(TAG,"--- onDestroy ---");
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(D) Log.d(TAG,"--- onConfigurationChanged ---");
}
@Override
public void onSetPlaying(boolean isPlaying){
this.isPlaying = isPlaying;
}
@Override
public void onGoalScored() {
if(teamFragment1 != null && teamFragment2 != null){
teamFragment1.allRobotsInside();
teamFragment2.allRobotsInside();
}
}
private void notifyToService(int what, String obj){
message = Message.obtain(null, what, obj);
try {
toService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void startTimer(){
notifyToService(CREATE_AND_START_TIMER,getIntent().getStringExtra(HALF_TIME));
}
class MessagesFromTimeServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case TimeService.CREATED_TIMER:
timerFragment.displayTime(TimerManager.timerFormat(Long.valueOf(msg.obj.toString())));
teamFragment1.setEditable(false);
teamFragment2.setEditable(false);
Log.d(TAG,"Timer creato");
break;
case TimeService.START_TIMER:
teamFragment1.setEditable(true);
teamFragment2.setEditable(true);
//timeService.showTimerNotification();
break;
case TimeService.UPDATE_TIMER:
Log.d(TAG,"Ricevuto dal service: "+TimerManager.timerFormat(Long.valueOf(msg.obj.toString())));
timerFragment.displayTime(TimerManager.timerFormat(Long.valueOf(msg.obj.toString())));
break;
case TimeService.PAUSE_TIMER:
teamFragment1.setEditable(false);
teamFragment2.setEditable(false);
//timeService.cancelTimerNotification();
break;
case TimeService.FINISH_TIMER:
Log.d(TAG,"Timer finito");
teamFragment1.setEditable(false);
teamFragment2.setEditable(false);
//timeService.cancelTimerNotification();
break;
case 55:
Log.d(TAG,"Ricevuto dal Service: "+msg.obj.toString());
break;
default:
super.handleMessage(msg);
}
}
}
}
public class TimerFragment extends Fragment{
private static final String TAG = "TimerFragment";
private static final boolean D = true;
private TextView timer;
private TextView currentHalf;
private BoardActivityCallback boardActivityCallback;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
boardActivityCallback = (BoardActivityCallback) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement BoardActivityCallback");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.timer,container,false);
if(D) Log.d(TAG,"--- onCreateView ---");
timer = (TextView)view.findViewById(R.id.timer);
currentHalf = (TextView)view.findViewById(R.id.currentHalf);
if(D) Log.d(TAG,"timer: "+timer.toString());
timer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boardActivityCallback.startTimer();
}
});
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onResume() {
super.onResume();
}
public void setHalfNumber(String halfNumber){
currentHalf.setText(halfNumber);
}
public void displayTime(String time){
timer.setText(time);
}
}
public class TimeService extends Service {
private static final String TAG = "TimeService";
private static final boolean D = true;
private final IBinder serviceBinder = new ServiceBinder();
private NotificationManager notificationManager;
private static final int TIMER_NOTIFICATION = 1;
private Messenger toActivity;
private Message message;
public static final int CREATED_TIMER = 0;
public static final int START_TIMER = 1;
public static final int UPDATE_TIMER = 2;
public static final int PAUSE_TIMER = 3;
public static final int FINISH_TIMER = 4;
private CountDownTimer timer;
private Messenger fromActivity = new Messenger(new IncomingHandler());
public class ServiceBinder extends Binder {
TimeService getService(){
return TimeService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
if(D) Log.d(TAG,"--- onBind ---");
//toActivity = intent.getParcelableExtra("Messenger");
//timer = new CountDownTimer(TimerManager.minSecToMillis(intent.getStringExtra("Halftime")));
//return serviceBinder;
return fromActivity.getBinder();
}
@Override
public void onCreate() {
super.onCreate();
if(D) Log.d(TAG,"--- onCreate ---");
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(D) Log.d(TAG,"--- onStartCommand ---");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
if(D) Log.d(TAG,"--- onDestroy ---");
cancelTimerNotification();
}
@Override
public boolean onUnbind(Intent intent) {
if(D) Log.d(TAG,"--- onUnbind ---");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
if(D) Log.d(TAG,"--- onRebind ---");
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(D) Log.d(TAG,"--- onConfigurationChanged ---");
}
public void showTimerNotification(){
// PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,BoardActivity.class), 0, null);
// Notification notification = new Notification.Builder(this)
// .setContentTitle(getResources().getString(R.string.app_name))
// .setContentText("The teams are playing a match")
// .setContentIntent(pendingIntent)
// .setSmallIcon(R.drawable.ic_launcher)
// .setWhen(0)
// .build();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Titolo")
.setContentText("Contenuto")
.setWhen(0);
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
String[] events = {"Line1","Line2","Line3","Line4"};
inboxStyle.setBigContentTitle("Dettagli:");
inboxStyle.setBigContentTitle("RoboSoccer Board");
for (int i=0; i < events.length; i++) {
inboxStyle.addLine(events[i]);
}
mBuilder.setStyle(inboxStyle);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
notificationManager.notify(TIMER_NOTIFICATION, notification);
}
public void cancelTimerNotification(){
if(notificationManager != null){
notificationManager.cancel(TIMER_NOTIFICATION);
}
}
private void notifyToBoard(int what, String obj){
message = Message.obtain(null, what, obj);
try {
toActivity.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void countDown(){
timer.startTimer();
}
class CountDownTimer extends Thread{
private long actualMillis;
private boolean isCountingDown;
public CountDownTimer(long millis){
actualMillis = millis;
isCountingDown = false;
notifyToBoard(CREATED_TIMER,String.valueOf(actualMillis));
}
@Override
public void run(){
notifyToBoard(START_TIMER,String.valueOf(actualMillis));
try{
do{
isCountingDown = true;
actualMillis -= 1000;
notifyToBoard(UPDATE_TIMER,String.valueOf(actualMillis));
Thread.sleep(1000);
}while (isCountingDown && actualMillis > 0);
}catch (InterruptedException ie){
isCountingDown = false;
}
isCountingDown = false;
notifyToBoard(FINISH_TIMER,String.valueOf(actualMillis));
}
public void startTimer(){
if(!isCountingDown){
this.start();
}
}
public void pauseTimer(){
this.interrupt();
notifyToBoard(PAUSE_TIMER,String.valueOf(actualMillis));
}
public void stopTimer(){
this.interrupt();
actualMillis = 0;
}
}
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case BoardActivity.GET_ACTIVITY_MESSENGER:
toActivity = msg.replyTo;
break;
case BoardActivity.CREATE_AND_START_TIMER:
//Log.d(TAG,"Ricevuto dall'Activity: "+msg.obj.toString());
//notifyToBoard(55,"Timer avviato");
timer = new CountDownTimer(TimerManager.minSecToMillis(msg.obj.toString()));
timer.startTimer();
break;
default:
super.handleMessage(msg);
}
}
}
}