自定义android计时器
自定义android计时器
龙扬凡 发表于4年前
自定义android计时器
  • 发表于 4年前
  • 阅读 1608
  • 收藏 0
  • 点赞 0
  • 评论 8

腾讯云 新注册用户 域名抢购1元起>>>   

摘要: 在做一个运动软件的时候需要用到计时器去计算运动时间,查了一下资料,发现android提供了Chronometer计时器控件,但是又发现这货使用起来受到诸多系统规则限制,而且一旦锁屏,还不会自动计时,真是坑爹货啊~于是乎自己做了个计时器,感觉自定义的东西就是原理简单易懂,操作方便,可移植性强。

自定义计时器的原理很简单,主要用到广播机制BroadcastReceiver来实现Activity和Service之间的通讯。

Service在后台开辟一个线程,使用Thread.sleep(1000)来实现每隔1秒钟给handler发送一次信息,告诉handler进行时间的递增,再利用广播,把hour、minute、second(小时、分钟、秒)三个数据发送给Activity,在TextView上显现出来。

效果图如下~

废话不多说,下面上源码~

先是Activity的

package com.hzy.mychronometer;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.example.chronometer.R;
import com.hzy.mychronometer.TimeService.MyBinder;
public class Mychronometer extends Activity
{
 protected static final String ACTIONServiceTOActivity = "Service-Activity";//TimeService把时间变化告诉Mychronometer的广播
 protected static final String ACTIONActivityToService = "Activity-Service";//Mychronometer告知TimeService停止、开始、清零的广播
 
 //定义控件
 private TextView hourTxt;
 private TextView minTxt;
 private TextView secTxt;
 private Button start;
 private Button stop;
 private Button setZero;
 //时间数据
 private int hour;
 private int min;
 private int sec;
 //广播
 private IntentFilter filter;
 private FromServiceReceiver receiver;//接收TimeService传来的时间变化数据
 
 private boolean ifBind;    //判断是否绑定了服务
 
 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.my_layout);
  
  ifBind=false;        //一开始没有绑定服务
  
  receiver=new FromServiceReceiver();   //初始化广播
  filter=new IntentFilter();
  filter.addAction(ACTIONServiceTOActivity);
  
  findview();         //初始化控件
  setListener();        //给控件设置监听
  hourTxt.setText("00");
  minTxt.setText("00");
  secTxt.setText("00");
 }
 
 
 @Override
 protected void onResume()
 {
  super.onResume();
  registerReceiver(receiver, filter);   //注册广播
 }

 @Override
 protected void onPause()
 {
  super.onPause();
  unregisterReceiver(receiver);    //注销广播
 }

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

 private void setListener()
 {
  start.setOnClickListener(new Button.OnClickListener()
  {
   @Override
   public void onClick(View v)
   {
    bindService();      //启动TimeService服务,开始计时
   }
  });
  stop.setOnClickListener(new Button.OnClickListener()
  {
   
   @Override
   public void onClick(View v)
   {
    stopService();      //暂停服务,暂停计时
   }
  });
  setZero.setOnClickListener(new Button.OnClickListener()//清零
  {
   
   @Override
   public void onClick(View v)
   {
    unBind();       //解除绑定,销毁Service
    hourTxt.setText("00");
    minTxt.setText("00");
    secTxt.setText("00");
   }
  });
 }
 
 protected void stopService()     //告诉TimeService.java停止线程
 {
  Intent intentStart=new Intent();
  intentStart.putExtra("StartOrNot",false);
  intentStart.setAction(ACTIONActivityToService);
  sendBroadcast(intentStart);
 }
 protected void unBind()       //解除绑定
 {
  if (ifBind)
  {
   Intent intentStart=new Intent();
   intentStart.putExtra("StartOrNot",false);
   intentStart.setAction(ACTIONActivityToService);
   sendBroadcast(intentStart);
   unbindService(conn);
   Toast.makeText(this, "unbind", Toast.LENGTH_LONG).show();
   ifBind=false;
  }
 }
 protected void bindService()     //启动TimeService服务,开始计时
 {
  if(!ifBind)//没有绑定则绑定
  {
   Intent intent=new Intent(Mychronometer.this, TimeService.class);
   bindService(intent, conn, Context.BIND_AUTO_CREATE);//绑定服务
   ifBind=true;
  }
  else//已经绑定则广播告诉TimeService.java开启线程
  {
   Intent intentStart=new Intent();
   intentStart.putExtra("StartOrNot",true);
   intentStart.setAction(ACTIONActivityToService);
   sendBroadcast(intentStart);
  }
 }
 
 private ServiceConnection conn=new ServiceConnection()
 {
  @Override
  public void onServiceDisconnected(ComponentName name)
  {
   
  }
  
  @Override
  public void onServiceConnected(ComponentName name, IBinder binder)
  {
  }
 };
 private void findview()
 {
  hourTxt=(TextView)findViewById(R.id.hour);
  minTxt=(TextView)findViewById(R.id.min);
  secTxt=(TextView)findViewById(R.id.sec);
  start=(Button)findViewById(R.id.ButtonStart);
  stop=(Button)findViewById(R.id.ButtonStop);
  setZero=(Button)findViewById(R.id.ButtonSet0);
 }
 class FromServiceReceiver extends BroadcastReceiver //接收TimeService.java返回的时间信息
 {
  @Override
  public void onReceive(Context context, Intent intent)
  {
   Bundle bundle1=intent.getExtras();
   hour=bundle1.getInt("hour",0);
   min=bundle1.getInt("min",0);
   sec=bundle1.getInt("sec",0);
   
   
   //把时间数据setText
   if(hour<10)
    hourTxt.setText("0"+hour);
   else
    hourTxt.setText(hour+"");
   
   if(min<10)
    minTxt.setText("0"+min);
   else
    minTxt.setText(min+"");
   
   if(sec<10)
    secTxt.setText("0"+sec);
   else
    secTxt.setText(sec+"");
  }
 }
}


 

最后是Service~

 package com.hzy.mychronometer;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
public class TimeService extends Service implements Runnable
{
 protected static final String ACTIONServiceTOActivity = "Service-Activity";//TimeService把时间变化告诉Mychronometer的广播
 protected static final String ACTIONActivityToService = "Activity-Service";//Mychronometer告知TimeService停止、开始、清零的广播
 private ServiceReceiver serviceReceiver;
 private IntentFilter filter;
 private MyBinder binder =new MyBinder();
 private Handler handler;
 private Thread timecountThread;    //告诉handler时间递增的线程
 private boolean flagIfContinnute;   //接收timecountThread线程的标志
 private boolean timeAdd;     //handler执行时间递增的信息标志
 
 //时间数据
 private int hour;
 private int min;
 private int sec;
 
 private Intent intentSendTime;    //传递时间数据的Intent
 @Override
 public IBinder onBind(Intent intent)
 {
  return binder;
 }
 @Override
 public boolean onUnbind(Intent intent)
 {
  return super.onUnbind(intent);
 }
 public class MyBinder extends Binder
 {
  public TimeService getService()
  {
   return TimeService.this;
  }
 }
 @Override
 public void onCreate()
 {
  super.onCreate();
  
  serviceReceiver=new ServiceReceiver();   //初始化广播
  filter=new IntentFilter();
  filter.addAction(ACTIONActivityToService);
  registerReceiver(serviceReceiver, filter);   //注册广播
  
  //初始化变量
  flagIfContinnute=false;
  hour=0;
  min=0;
  sec=0;
  intentSendTime=new Intent();
  
  
  
  //接收线程的信息实现时间递增
  handler=new Handler()
  {
   public void handleMessage(Message msg)
   {
    timeAdd = msg.getData().getBoolean("timeadd");
    //模拟时间变化规律
    if(timeAdd)
    {
     if(sec+1==60)
     {
      if(min+1==60)
      {
       hour++;
       min=0;
      }
      else
      {
       min++;
      }
      sec=0;
     }
     else
     {
      sec++;
     }
    }
    
    intentSendTime.putExtra("hour", hour);
    intentSendTime.putExtra("min", min);
    intentSendTime.putExtra("sec", sec);
    
    intentSendTime.setAction(ACTIONServiceTOActivity);
    sendBroadcast(intentSendTime);
   }
  };
  timecountThread=new Thread(this);
  timecountThread.start();
 }
 
 @Override
 public void onDestroy()
 {
  super.onDestroy();
  unregisterReceiver(serviceReceiver);
 }
 @Override
 public void run()
 {
  flagIfContinnute=true;
  while(flagIfContinnute)
  {
   Message msg = handler.obtainMessage();//每一次都必须新建msg!
   Bundle data = new Bundle();
   data.putBoolean("timeadd", true);
   msg.setData(data);
   handler.sendMessage(msg);
   try
   {
    Thread.sleep(1000);//每隔一秒钟告诉handler时间递增1
   } catch (InterruptedException e)
   {
    e.printStackTrace();
   }
  }
 }
 
 class ServiceReceiver extends BroadcastReceiver
 {
  @Override
  public void onReceive(Context context, Intent intent)
  {
   Bundle bundle1=intent.getExtras();
   boolean temp=bundle1.getBoolean("StartOrNot",true);
   if(!flagIfContinnute&&temp)//本来没有启动线程而Activity告知启动线程,那么就启动
   {
    timecountThread=new Thread(TimeService.this);
    timecountThread.start();
   }
   if(flagIfContinnute&&!temp)//本来已经启动线程而Activity告知停止线程,那么就停止
    flagIfContinnute=false;
  }
 }
}

自定义计时器就是这么简单。。。。

需要源码的留言吧~
标签: 自定义 计时器
共有 人打赏支持
粉丝 0
博文 1
码字总数 1206
评论 (8)
龙扬凡
0
许心炜

引用来自“龙扬凡”的评论

0
哥们 方便把你的工程发给我么 跪求啊 542065452@qq.com 万分感谢
龙扬凡

引用来自“龙扬凡”的评论

0

引用来自“许心炜”的评论

哥们 方便把你的工程发给我么 跪求啊 542065452@qq.com 万分感谢
http://pan.baidu.com/s/1bngVZBL 已经上传到网盘了
龙扬凡
http://pan.baidu.com/s/1bngVZBL
许心炜

引用来自“龙扬凡”的评论

http://pan.baidu.com/s/1bngVZBL
方便留个邮箱么 能不能请教点问题 我用了下你的代码 可是bindservice执行后不能执行service的oncreate()方法 导致service不能启动 不知道为什么
hxl8811
h2562027@163.com讨教源码
开发军
445010487@qq.com 请赐源码
正在前行ay
1137211202@qq.com,谢谢大好人,这是我的邮箱,可以发一份源码我吗
×
龙扬凡
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: