Android创建Service后台常驻服务并使用Broadcast通信
来源:互联网 发布:好听的淘宝优惠群取名 编辑:程序博客网 时间:2024/06/10 07:30
1、概述
1.1 背景
一直想玩智能小车,考虑了手机作为上位机的角色,所以还是重拾一下Android。花了半天时间搭建环境eclipse + Java + Android SDK,又花了大半天时间查了查资料,最终把这份代码给整理出来,与大家分享一下。
1.2 需求
需求非常简单:用户点击按钮,APP获得事件进行处理并反馈,处理的事件为后续再扩展。
需求分解为:
1)界面启动(Activity),监听用户点击按钮的事件;
2)界面启动后运行后台服务(Service),Service负责处理复杂逻辑事件(后续扩展);
3)后台服务不随界面退出而退出;
4)后台服务主线程执行不耗时的逻辑,子线程执行耗时操作(阻塞的操作)。
2、知识点
2.1 service
概念:Service是Android程序中四大基础组件之一,它和Activity一样都是Context的子类,只不过它没有UI界面,是在后台运行的组件。其它应用的组件可以启动一个服务运行于后台,即使用户切换到另一个应用也会继续运行[1]。
使用方法:Service对象不能自己启动,需要通过某个Activity、Service或者其他Context对象来启动。文章[2] 详细地讲述Service有三种启动方法,以下为摘要:
1) context.startService() 启动流程(后台处理工作)
只能实现启动和停止服务使用Intent进行数据传递,通过服务中的onStartCommand方法进行接受
生命周期:context.startService() -> onCreate() -> onStartCommand() -> Service running ->
context.stopService() -> onDestroy() -> Service stop
2) context.bindService() 启动流程(在本地同一进程内与Activity交互),单向交互
生命周期:context.bindService() -> onCreate() -> onBind() -> Service running ->
onUnbind() -> onDestroy() -> Service stop
3) 使用AIDL方式的Service(进行跨进程通信),双向交互
高级:跨进程通信时使用。
2.2 Broadcast
老罗书中提到在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制;这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用。
文章[3]给出使用方法 以及Demo:
1)首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象,然后通过调用 Context.sendBroadcast()、sendOrderBroadcast()或sendStickyBroadcast()方法,把 Intent对象以广播方式发送出去。
2)当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法。
另外,广播注册的方式上又分为静态与动态的方式,下面的例子将使用动态注册的广播完成Activity 与 Service间通信的方法。
3、code
code阶段最大的帮助就是season同学的文章[4],这也是后续智能小车的思路,而回到本次主题《Android创建Service后台常驻服务并使用Broadcast通信》,所以做了一个精简的版本。下面对代码进行关键点的说明。
3.1 Service
使用的是startService的方式,回顾一下生命周期: context.startService() -> onCreate() -> onStartCommand() -> Service running ->context.stopService() -> onDestroy() -> Service stop
首先在onStartCommand方法里面动态注册广播,广播将用于接收Activity发送过来的命令。
/* Called when Activity startService */@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {cmdReceiver = new CommandReceiver();IntentFilter filter = new IntentFilter();filter.addAction("android.intent.action.cmdservice");
registerReceiver(cmdReceiver, filter);myStartService();return super.onStartCommand(intent, flags, startId);}
然后进入myStartService()准备开启子线程,随后的耗时操作将放置到子线程中,如串口的数据读取。
/* * Called by onStartCommand, initialize and start runtime thread */private void myStartService() {//TODO initialize devicethreadFlag = true;mThread = new MyThread();mThread.start();}线程类,threadFlag控制enable,现暂时放置的“耗时操作”由showToast消息提示客串呵呵。
/* * Thread runtime */public class MyThread extends Thread { @Overridepublic void run() {super.run();// TODO runtimewhile( threadFlag ) {Log.d(TAG, "Thread pulse");showToast("Service Thread pulse");try{Thread.sleep(10000);}catch(Exception e){e.printStackTrace();}}}}showToast其实就是发送广播给Activity,告知其在界面上显示消息内容
/* * Tell Activity to show message on screen */public void showToast(String str) {Intent intent = new Intent();intent.putExtra("cmd", CMD_SHOW_TOAST);intent.putExtra("str", str);intent.setAction("android.intent.action.cmdactivity");sendBroadcast(intent); }同时考虑一下,Service在主线程中也是得需要接收来着Activity的命令,这时就看看CommandReceiver这个类了。
广播数据中定义了两个变量,cmd 和 value, cmd表示系统类型, value则是具体操作的数据,这时myHandlerData就可以自己发挥了,如发送串口命令到下位机...
/* * BroadcastReceiver for Activity */private class CommandReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {if ( intent.getAction().equals("android.intent.action.cmdservice") ){int cmd = intent.getIntExtra("cmd", -1);int value = intent.getIntExtra("value", -1);if ( cmd == CMD_STOP_SERVICE ) {myStopService();}else if ( cmd == CMD_SEND_DATA ) {myHandlerData(value);}}}}然后就是Service生命周期的结束,取消广播的注册,结束进程。
其实这里也有疑问点:如何才能触发onDestroy?Activity显然是不能关闭他了。
@Overridepublic void onDestroy() {Log.i(TAG, "onDestroy()");super.onDestroy();this.unregisterReceiver(cmdReceiver);threadFlag = false;boolean retry = true;while ( retry ) {try {retry = false;mThread.join();} catch (Exception e) {e.printStackTrace();}}}
3.2 Activity
主进程通过startService(mIntent) 来开启服务,当然也定义了4个按钮来测试发送命令@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mBtn1 = (Button)findViewById(R.id.button1);mBtn1.setTag(1);mBtn1.setOnClickListener(new mButtonSendClickListener());mBtn2 = (Button)findViewById(R.id.button2);mBtn2.setTag(2);mBtn2.setOnClickListener(new mButtonSendClickListener());mBtn3 = (Button)findViewById(R.id.button3);mBtn3.setTag(3);mBtn3.setOnClickListener(new mButtonSendClickListener());mBtn4 = (Button)findViewById(R.id.button4);mBtn4.setTag(4);mBtn4.setOnClickListener(new mButtonSendClickListener());mIntent = new Intent(MainActivity.this, MyService.class); startService(mIntent);Log.i(TAG, "startService");}然后咱们先来看看发送命令到Service这一部分,先是监听点击事件,然后对应不同按钮的tag值发送不同的广播内容。
到这里仍然不清楚广播用法的话你可以参照一下文章[4]的Demo。
这里面用多个按钮共用一个监听进行处理的方式[6]。
/* * Send message to service */public void mSendBroadcast(int cmd, int value) {Intent intent = new Intent();intent.setAction("android.intent.action.cmdservice");intent.putExtra("cmd", cmd);intent.putExtra("value", value); sendBroadcast(intent);Log.d(TAG, "sendBroadcast: " + CMD_SEND_DATA + " " + value);}/* * Handle click event */public class mButtonSendClickListener implements OnClickListener{@Overridepublic void onClick(View v) {// send broadcastint cmd = CMD_SEND_DATA;int value = (Integer) v.getTag();mSendBroadcast(cmd, value);}}
/* * Send message to service */public void mSendBroadcast(int cmd, int value) {<span style="white-space:pre"></span>Intent intent = new Intent();<span style="white-space:pre"></span>intent.setAction("android.intent.action.cmdservice");<span style="white-space:pre"></span>intent.putExtra("cmd", cmd);<span style="white-space:pre"></span>intent.putExtra("value", value); <span style="white-space:pre"></span>sendBroadcast(intent);<span style="white-space:pre"></span>Log.d(TAG, "sendBroadcast: " + CMD_SEND_DATA + " " + value);}另外不要忘了等待Service的消息回馈,先注册一个广播
@Overrideprotected void onResume() {super.onResume();Log.i(TAG, "onResume");mReceiver = new MyReceiver();IntentFilter mFilter=new IntentFilter();mFilter.addAction("android.intent.action.cmdactivity");MainActivity.this.registerReceiver(mReceiver, mFilter);}监听方法,主要就是对接收到Service的字符串进行显示
/* * BroadcastReceiver for Service */public class MyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if(intent.getAction().equals("android.intent.action.cmdactivity")){Bundle bundle = intent.getExtras();int cmd = bundle.getInt("cmd");if(cmd == CMD_SHOW_TOAST){<span style="white-space:pre"></span>String str = bundle.getString("str");<span style="white-space:pre"></span>myShowToast(str);}else if(cmd == CMD_SYSTEM_EXIT){System.exit(0);}}}}
/* * Show message on screen */public void myShowToast(String str) {<span style="white-space:pre"></span>Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();<span style="white-space:pre"></span>}
4、结束
界面的效果图如下,这次先简单地将框架准备好,方便下次进行扩展。
Broadcast主要就是将数据插入到Intent对象中进行发送、接收。
这次使用startService将启动在后台服务一直执行,后续检查是否会造成CPU浪费,是否要改回Bind的方式。
工程下载地址:http://download.csdn.net/detail/stayneckwind2/8610921
参考文章:
[1] Android Service 详解, http://www.cnblogs.com/mengdd/archive/2013/03/24/2979944.html
[2] 浅谈Service, http://www.2cto.com/kf/201504/390385.html
[3] Android之Broadcast, BroadcastReceiver , http://www.cnblogs.com/playing/archive/2011/03/23/1992030.html
[4] Android 与Arduino蓝牙串口的通信设计, http://blog.csdn.net/cen616899547/article/details/6728040
[5] Broadcast简单实例, http://blog.csdn.net/xyylchq/article/details/6824992
[6] Android多个按钮的处理方法, http://blog.csdn.net/woshixuye/article/details/8331335
0 0
- Android创建Service后台常驻服务并使用Broadcast通信
- Android创建Service后台常驻服务并使用Broadcast通信
- 使用 Broadcast 与后台 Service 服务通信
- android service后台服务生命周期与常驻后台
- Android Service常驻后台 守护程序
- android service 常驻后台, 不被清理
- android后台服务service全解析(上)--service的使用与本地通信
- service常驻后台
- android后台服务service全解析(下)--service远程通信
- Android 使用IPC和后台Service通信
- android Service后台服务的使用
- Android前台画面和后台service之间通信的方法之Broadcast
- Android前台画面和后台service之间通信的方法之Broadcast
- Android前台画面和后台service之间通信的方法之Broadcast(转)
- Android前台画面和后台service之间通信的方法之Broadcast
- Android前台画面和后台service之间通信的方法之Broadcast
- Android service、broadcast后台启动Activity
- Android Service 双进程常驻后台(2)
- uestc 11 Judgment Day
- 第9题
- 基站选址
- google 登录 login api php
- RT5350 HLK-RM04模块配置OpenWRT
- Android创建Service后台常驻服务并使用Broadcast通信
- Code Hunt SECTOR 02 LOOPS
- uva_10246_Asterix and Obelix(最短路)
- 分析源代码编译链接过程和shell中ELF格式可执行文件的初始化执行过程
- request.getparameter中文乱码问题解决方案
- 条款27:尽量少做转型操作
- [BZOJ2434]NOI2011阿狸的打字机|AC自动机|fail树|树状数组
- nyoj-220 推桌子
- 设计模式--访问者模式