文档章节

自定义android计时器

龙扬凡
 龙扬凡
发布于 2014/05/01 21:03
字数 1206
阅读 1613
收藏 0
点赞 0
评论 8

自定义计时器的原理很简单,主要用到广播机制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
作品 0
广州
程序员
加载中

评论(8)

正在前行ay
正在前行ay
1137211202@qq.com,谢谢大好人,这是我的邮箱,可以发一份源码我吗
开发军
445010487@qq.com 请赐源码
h
hxl8811
h2562027@163.com讨教源码
许心炜
许心炜

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

http://pan.baidu.com/s/1bngVZBL
方便留个邮箱么 能不能请教点问题 我用了下你的代码 可是bindservice执行后不能执行service的oncreate()方法 导致service不能启动 不知道为什么
龙扬凡
龙扬凡
http://pan.baidu.com/s/1bngVZBL
龙扬凡
龙扬凡

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

0

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

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

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

0
哥们 方便把你的工程发给我么 跪求啊 542065452@qq.com 万分感谢
龙扬凡
龙扬凡
0
Android动画:献上一份详细 & 全面的动画知识学习攻略

前言 动画的使用 是 开发中常用的知识 可是动画的种类繁多、使用复杂,每当需要 采用自定义动画 实现 复杂的动画效果时,很多开发者就显得束手无策 本文将献上一份动画的全面介绍攻略,包括动...

Carson_Ho ⋅ 06/06 ⋅ 0

Android插件化原理(一)Activity插件化

相关文章 Android深入四大组件系列 Android解析AMS系列 Android解析ClassLoader系列 前言 四大组件的插件化是插件化技术的核心知识点,而Activity插件化更是重中之重,Activity插件化主要有三...

刘望舒 ⋅ 05/29 ⋅ 0

Android 动画:这是一份详细 & 清晰的 动画学习指南

前言 动画的使用 是 开发中常用的知识 可是动画的种类繁多、使用复杂,每当需要 采用自定义动画 实现 复杂的动画效果时,很多开发者就显得束手无策 本文将献上一份动画的全面介绍攻略,包括动...

Carson_Ho ⋅ 05/03 ⋅ 0

android悬浮窗、收款二维码、相机处理、事件通知库、NFC读取等源码

Android精选源码 一个漂亮而强大的自定义view SeekBar(http://www.apkbus.com/thread-598080-1-1.html) 适用于Android的简单NFC读取源码(http://www.apkbus.com/thread-598082-1-1.html) 安卓......

逆鳞龙 ⋅ 04/24 ⋅ 0

android蓝牙手柄、仿QQ看房、仿慕课网、数据库二维码框架等源码

Android精选源码 可自定义图片指示器并支持自定义Tab宽度的TabLayout源码(http://www.apkbus.com/thread-599243-1-1.html) android蓝牙控制手柄操作源码(http://www.apkbus.com/thread-59928...

逆鳞龙 ⋅ 05/15 ⋅ 0

andriod-四大组件之广播Broadcast-短信的收发

我想几乎所有的安卓开发者,第一个接触到的四大组件之一就是activity,而我在之前的文章中也写过, 在activity里面getContext是大佬级别的存在(可以看前几章), 那么四大组件中的广播Broad...

九尾74 ⋅ 05/24 ⋅ 0

Android系统源码分析团体项目BeesAndroid正式上线啦

嗨,BeesAndroid开源技术小组正式成立啦,Bees,即蜜蜂,取义分享、合作与奉献的意思,这也是BeesAndroid小组的宗旨,我们第一个团体项目BeesAndroid也于2018年3月6日同步上线,该项目的前 ...

郭孝星 ⋅ 03/08 ⋅ 0

Android P 应用兼容常见错误及建议

从 2018 年 3 月初我们发布 Android P 开发者预览版以来,很多开发者都对当前常见应用在 Android P 上做了一些兼容性测试,我们在这里总结了一些常见的问题,以及它们发生的原因和建议的修改...

谷歌开发者 ⋅ 04/25 ⋅ 0

彻底理解 Android 中的阴影

如果我们想创造更好的 Android App,我相信我们需要遵循 Material Design 的设计规范。一般而言,Material Design 是一个包含光线,材质和投影的三维环境。如果我们想要在 App 的开发过程中,...

丁佳辉 ⋅ 04/18 ⋅ 0

Android ------ 美团的Lint代码检查实践

概述 Lint是Google提供的Android静态代码检查工具,可以扫描并发现代码中潜在的问题,提醒开发人员及早修正,提高代码质量。除了Android原生提供的几百个Lint规则,还可以开发自定义Lint规则...

切切歆语 ⋅ 04/16 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

服务网关过滤器

过滤器作用 我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了。但是,每个客户端用户请求微服务应用提供的接口时,它们的访问权限往往都需要有一定的限制,系统并不会...

明理萝 ⋅ 16分钟前 ⋅ 1

【2018.06.21学习笔记】【linux高级知识 14.1-14.3】

14.1 NFS介绍 NFS服务全称是NetWork File System:网络文件系统,最早有sun公司开发的,4.0版本由Netapp公司开发,是基于RPC远程过程调用(Remote Procedure Call)协议的服务。 14.2 NFS服务...

lgsxp ⋅ 24分钟前 ⋅ 0

Day18 vim编辑模式、命令模式与练习

编辑模式 命令模式 :nohl 不高亮显示 :x与:wq类似,如果在更改文件之后操作,两者效果一样;如果打开文件,没有任何操作; :wq会更改mtime,但是:x不会。 练习题 扩展 vim的特殊用法 ht...

杉下 ⋅ 28分钟前 ⋅ 0

Enum、EnumMap、EnumSet

1、Enum 不带参数 public enum Car { AUDI { @Override public int getPrice() { return 25000; } }, MERCEDES { ......

职业搬砖20年 ⋅ 29分钟前 ⋅ 0

Java中的锁使用与实现

1.Lock接口 锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。 在Lock出现之前,java程序是靠synchronized关键字实现锁功能的,而Java SE5之后,...

ZH-JSON ⋅ 30分钟前 ⋅ 0

线程组和 ThreadLocal

前言 在上面文章中,我们从源码的角度上解析了一下线程池,并且从其 execute 方法开始把线程池中的相关执行流程过了一遍。那么接下来,我们来看一个新的关于线程的知识点:线程组。 线程组 ...

猴亮屏 ⋅ 31分钟前 ⋅ 0

相对路径和绝对路径

基本概念   文件路径就是文件在电脑中的位置,表示文件路径的方式有两种,相对路径和绝对路径。在网页设计中通过路径可以表示链接,插入图像、Flash、CSS文件的位置。   物理路径:物理路...

临江仙卜算子 ⋅ 35分钟前 ⋅ 0

消息队列属性及常见消息队列介绍

什么是消息队列? 消息队列是在消息的传输过程中保存消息的容器,用于接收消息并以文件的方式存储,一个队列的消息可以同时被多个消息消费者消费。分布式消息服务DMS则是分布式的队列系统,消...

中间件小哥 ⋅ 37分钟前 ⋅ 0

java程序员使用web3j进行以太坊开发详解

如何使用web3j为Java应用或Android App增加以太坊区块链支持,教程内容即涉及以太坊中的核心概念,例如账户管理包括账户的创建、钱包创建、交易转账,交易与状态、智能合约开发与交互、过滤器...

笔阁 ⋅ 38分钟前 ⋅ 0

vim编辑模式、vim命令模式

vim编辑模式 使用vim filename 进入的界面是一般模式,在这个模式下虽然我们能够查看,复制,剪切,粘贴,但是不能编辑新的内容,如何能直接写入东西呢?这就需要进入编辑模式了,从一般模式...

李超小牛子 ⋅ 40分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部