Android中Service的通信机制
来源:互联网 发布:电脑网卡mac地址怎么查 编辑:程序博客网 时间:2024/06/07 09:30
在上一篇博客中http://blog.csdn.net/redoq/article/details/52142868,我们对Service进行了粗略的讲解,这一篇博客我将介绍Service的通信机制,不足之处望指正。
由于Service的启动分为两种,所以我把Service的通信分为两种介绍
一:对于通过startService启动的服务
我们可以通过下面的代码将数据发送到Service中
启动服务的Activity中的代码
Intent i = new Intent(this,MyService.class);i.putExtra("data","send data");...startService(i);
MyService中的代码,由于使用的是startService启动服务,所以这里用onStartCommand来接收数据
private String data = ""; @Override public int onStartCommand(final Intent intent, int flags, int startId) { data = intent.getStringExtra("data"); //通过onStartCommand中的intent参数获取数据 System.out.println("接收到的数据为:" + data); return super.onStartCommand(intent, flags, startId); }输出结果 接收到的数据为:send data
通过startService传递数据虽然简单方便,但是不能将MyService中的数据返回到调用它的Activity,除非使用广播,我将在后面对广播进行讲解。
=============================================================================
二、通过bindService绑定服务传递数据
1、首先,我们重写MyService中的onBind()并新建一个类继承Binder
public class MyService extends Service { private String data = ""; public MyService() { } @Override public IBinder onBind(Intent intent) { return new MyBinder(); //将MyBinder对象返回给启动MyService的Activity } public class MyBinder extends Binder { //Binder类实现了IBinder接口 public void setData(String data) { MyService.this.data = data; //修改data的值 } }}
2、然后我们使用bindService绑定服务并重写onServiceConnected()和onServiceDisconnected()
MainActivity代码
private MyService.MyBinder binder = null; //新建一个MyBinder对象,用于接收MyService返回的MyBinder对象 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ binder.setData("修改MyService中data的值 "); } }); bindService(new Intent(this,MyService.class),this,Context.BIND_AUTO_CREATE); } @Override public void onServiceConnected(ComponentName name, IBinder service) { binder = (MyService.MyBinder)service; //接收MyService返回的MyBinder对象 } @Override public void onServiceDisconnected(ComponentName name) { }
通过上面的绑定服务来直接调用方法就可以将数据传递给Service,这种方法比startService更加方便同时也更加高效。
===========================================================================================
三、如何将服务中状态的改变通知给外界,比如Service执行某些操作之后想要更新主UI线程
我们知道,在辅线程中是不能进行主UI线程更新操作的,有些人可能听过这样的口诀“主线程不做耗时操作,子线程不更新UI”
1、使用接口回调的方式更新UI线程
我们在MyService中写一个接口
public static interface Callback{ void onDataChange(String data);}
为了大家能直观的理解,我把MyService的代码全列出
public class MyService extends Service { private boolean running = false; private CallBack mCallBack = null; public MyService() { } @Override public void onCreate() { super.onCreate(); running = true; new Thread() { @Override public void run() { super.run(); int i = 0; while (running) { i++; if (mCallBack != null) { mCallBack.onDataChange(i + ""); //把更新的内容传出去 } try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public void onDestroy() { super.onDestroy(); running = false; } @Override public IBinder onBind(Intent intent) { return new MyBinder(); } public class MyBinder extends Binder{ public MyService getMyService(){ return MyService.this; } } public CallBack getCallBack() { return mCallBack; } public void setCallBack(CallBack callBack) { mCallBack = callBack; } public static interface CallBack { void onDataChange(String data); }}
下面的内容是Activity中的部分代码,控件的初始化代码没给
private MyService.MyBinder binder = null; private TextView tv; @Override public void onServiceConnected(ComponentName name, IBinder service) { binder = (MyService.MyBinder) service; //获取MyService中onBind返回的 MyBinder对象 binder.getMyService().setCallBack(new MyService.CallBack() { @Override public void onDataChange(String data) { //这里不能直接更新UI,因为辅线程不能更新UI主线程 Message message = new Message(); Bundle b = new Bundle(); b.putString("data", data); message.setData(b); mHandler.sendMessage(message); //把数据通过Message发送到Handler中 } }); } private Handler mHandler = new Handler() { //定义一个Handler对象,用于更新UI线程 @Override public void handleMessage(Message msg) { super.handleMessage(msg); tv.setText(msg.getData().getString("data")); //更新UI } }; @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bindService: bindService(new Intent(MainActivity.this, MyService.class), this, Context.BIND_AUTO_CREATE); break; } }
2、使用广播(broadcast)将MyService中的数据传到外界,更新UI
当MyService中的数据变化时就发送一条广播,然后在Activity中已经注册的广播接收器就能接收到广播并获取内容进行UI更新。
(1)首先在Activity中注册广播
public class MainActivity extends Activity implements View.OnClickListener { private TextView tv; private MsgReceiver msgReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); findViewById(R.id.startService).setOnClickListener(this); findViewById(R.id.stopService).setOnClickListener(this); } //广播接收器 public class MsgReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { tv.setText(intent.getIntExtra("data", 0)+""); //接收到广播数据后更新UI } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.startService: msgReceiver = new MsgReceiver(); //定义一个广播接收器 // IntentFilter intentFilter = new IntentFilter(MyService.ACTION); //也可像下面那样写 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(MyService.ACTION); //添加action,要和发送广播的Intent中的action一致 registerReceiver(msgReceiver,intentFilter); //注册广播 startService(new Intent(this, MyService.class)); //启动服务 break; case R.id.stopService: stopService(new Intent(this, MyService.class)); //停止服务 unregisterReceiver(msgReceiver); //注销广播 } }}
(2)、在MyService中将需要传出的数据通过广播发送出去
public class MyService extends Service { private boolean running = false; public static final String ACTION = "包名.intent.action.MyService"; @Override public void onCreate() { super.onCreate(); running = true; new Thread() { @Override public void run() { super.run(); int i = 0; while (running) { i++; Intent intent = new Intent( ACTION ); //添加action,要和Activity中接收广播的action一致 intent.putExtra("data", i); sendBroadcast(intent); //每次内容更改都发送一条广播 try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public void onDestroy() { super.onDestroy(); running = false; } @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); }}
- Android中Service的通信机制
- Android Service的Binder通信机制
- Android之Service与Activity通信机制
- Android之Service与Activity通信机制
- Android Service IPC通信之Messenger机制
- Android中Activity、Service和线程之间的通信
- Android中Activity、Service和线程之间的通信
- Android中Activity、Service和线程之间的通信
- Android中Activity、Service和线程之间的通信
- Android中Activity、Service和线程之间的通信
- Android中Service与跨进程的Activity通信。
- Android中Activity与Service之间的通信
- Android中Activity,Service,Thread三者之间的通信
- Android中Activity、Service和线程之间的通信
- Android中Activity、Service和线程之间的通信
- Android中Activity、Service和线程之间的通信
- Android中Activity、Service和线程之间的通信
- Android中Activity、Service和线程之间的通信
- Flask Web 开发 数据库操作 Sqlalchemy
- ex18.py
- 单例模式
- android 网络图片按原始比例显示在屏幕上
- ex19.py
- Android中Service的通信机制
- arm64 memory node的解析
- Kerberos协议
- UbuntuServer14.04下搭建LAMP环境
- 梅森素数 乘法换加法取模计算 模板
- c语言/c++编程题 之 Absolute Value
- ubuntu 14.04 opera浏览器flash插件安装
- 10047---java动态代理(JDK和cglib)
- 数据结构实验之二叉树二:遍历二叉树