在Android服务中使用Timer

时间:2012-12-05 10:49:18

标签: android android-service

我有一个服务作为另一个应用程序的一部分充当内部时钟,它包含一个每1秒运行一次的Timer来更新时间。

问题是,当我关闭并重新打开应用程序时,服务绑定自身,所有代码再次在服务中运行,然后每秒有两个计时器,依此类推。

我尝试过关注本地服务示例,但同样的事情发生在http://developer.android.com/reference/android/app/Service.html#LocalServiceSample

是否与服务的绑定/取消绑定有关?

我想只运行一个进程,所以我正在寻找一种方法来确定进程是否已经运行,如果没有则启动它。

本地服务 `public class LocalService extends Service {

// This is the object that receives interactions from clients.
private final IBinder mBinder = new LocalBinder();

private  long dateOfLastSync;
private  long timeNow;

private final Handler handler = new Handler();
private static Timer timer = new Timer();
private Context ctx;


/**
 * Class used for the client Binder.  Because we know this service always
 * runs in the same process as its clients, we don't need to deal with IPC.
 */
public class LocalBinder extends Binder {

    // The LocalBinder provides the getService() method for clients to retrieve the current instance of LocalService.
    LocalService getService() {
        Log.d("INTERNALCLOCK", "getService");
        // Return this instance of LocalService so clients can call public methods
        return LocalService.this;
    }
}

@Override
public void onCreate() {
    Log.d("INTERNALCLOCK", "onCreate");
    ctx = this; 
    startService();        
}

@Override
public void onDestroy() {
    Log.d("INTERNALCLOCK", "onDestroy");
    Toast.makeText(this, "Service Stopped ...", Toast.LENGTH_SHORT).show();

}

private void startService()
{           
    timer.scheduleAtFixedRate(new mainTask(), 0, 1000);
}

private class mainTask extends TimerTask
{ 
    public void run() 
    {
        toastHandler.sendEmptyMessage(0);
    }
}    

public void getTimeFromServer()  {
    FetchServerTime fetchTime = new FetchServerTime();
    fetchTime.execute();

}

@Override
public IBinder onBind(Intent intent) {
    Log.d("INTERNALCLOCK", "onBind");
    getTimeFromServer();


    return mBinder;
}

/** method for clients */
public long getTimeNow() {
    Log.d("INTERNALCLOCK", "getTimeNow");
  return timeNow;
}

public void startTimeCounter() {
    Log.d("INTERNALCLOCK", "startTimeCounter");

}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d("INTERNALCLOCK", "onStartCommand");

    return START_STICKY;
}

private final Handler toastHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        timeNow += 1000;
        Log.d("INTERNALCLOCK", "time is " + timeNow);
        Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_SHORT).show();
    }
}; 

 class FetchServerTime extends AsyncTask<Integer, String, Long> {

    private String mUrl;
    private Date date;
    private AlarmManager mAlarmManager;

    public FetchServerTime() {
        mUrl = "XXX";
    }

    @Override
    protected Long doInBackground(Integer... params) {
        (get server time code)
    }

    @Override
    protected void onPostExecute(Long result) {
        super.onPostExecute(result);
        Log.d("INTERNALCLOCK", "Server time on post execute: " + result);
        timeNow = result;
        dateOfLastSync = result;
    }




}

`

InternalClockActivity

 public class InternalClockActivity extends Activity implements CanUpdateTime {
private TextView timeLabel;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Log.d("INTERNALCLOCK", "onCreate - main");

    timeLabel = (TextView) findViewById(R.id.time);

    doBindService();
}

private LocalService mBoundService;

private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
        // This is called when the connection with the service has been
        // established, giving us the service object we can use to
        // interact with the service.  Because we have bound to a explicit
        // service that we know is running in our own process, we can
        // cast its IBinder to a concrete class and directly access it.


        mBoundService = ((LocalService.LocalBinder)service).getService();

    }

    public void onServiceDisconnected(ComponentName className) {
        // This is called when the connection with the service has been
        // unexpectedly disconnected -- that is, its process crashed.
        // Because it is running in our same process, we should never
        // see this happen.
        mBoundService = null;
    }
};

private boolean mIsBound;

void doBindService() {
    // Establish a connection with the service.  We use an explicit
    // class name because we want a specific service implementation that
    // we know will be running in our own process (and thus won't be
    // supporting component replacement by other applications).

    bindService(new Intent(InternalClockActivity.this, 
            LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
    mIsBound = true;
}

void doUnbindService() {
    if (mIsBound) {
        // Detach our existing connection.
        unbindService(mConnection);
        mIsBound = false;
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    doUnbindService();
}

public void updateTime(String time){

    timeLabel.setText(time);

}
}

1 个答案:

答案 0 :(得分:0)

我刚刚创建了一些静态变量来查看计时器是否正在运行,即

private static boolean isDownloadTaskRunning = false;

private void startService()
{
    if (!isDownloadTaskRunning) {
        // Timers are not running already

        // start timer to download date at intervals
        timerToDownloadNewData.scheduleAtFixedRate(new DownloadDateTask(), 0, TIMES.FIFTEEN_MINS.getSeconds());

        // set running to true
        isDownloadTaskRunning = true;
    }
}