[Android学习笔记5]四大应用组件之一:Service 下
绑定方式的Service使用
在实现绑定服务时,最重要的是定义onBind()回调方法返回的接口,有三种方式:
1. 继承Binder类
2. 使用Messenger
3. 使用AIDL
这里对1,2方式进行分析。
1.继承Binder类
如果你的服务是你的应用程序的私有服务,并且跟客户端运行在同一个进程中,那么就应该通过继承Binder类来创建你的接口,并且佛从onBind()方法中返回这个接口的一个实例。客户端接收这个Binder对象,并且能够使用这个对象直接访问Binder类中实现的或Service中的公共方法。
使用官方SDK文档中的例子:
ServiceShow.java
package com.luoye.servicelearn; import java.util.Random; import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder; public class ServiceShow extends Service{ private final IBinder binder = new LocalBinder();//创建Service的内部IBinder对象 public class LocalBinder extends Binder
{
ServiceShow getService() //实现Binder自己的方法,这里返回Service对象的引用
{
return ServiceShow.this;
}
} public int getRandomNumber()
{
return (new Random()).nextInt(100);
} @Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
//返回一个IBinder对象,即Service的内部IBinder对象,作为ServiceConnection中onServiceConnected方法的IBinder传入
return binder;
} }
MainActivity.java
package com.luoye.servicelearn; import com.luoye.servicelearn.ServiceShow.LocalBinder; import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.Menu;
import android.view.View;
import android.widget.Toast; public class MainActivity extends Activity { ServiceShow localService;
boolean bound = false; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} public void buttonOnClickListener(View v)
{
switch(v.getId())
{
case R.id.start_service1:
Intent intent_start = new Intent(this, ServiceShow.class);
//绑定Service 第二个参数为ServiceConnection对象,由于bindService是异步的,
//bindService()方法立即返回并且不返回IBinder对象,所以需要在ServiceConnection的方法中去处理
//BIND_AUTO_CREATE表示if Service不存在,即onCreate()
bindService(intent_start, connection, Context.BIND_AUTO_CREATE);
break;
case R.id.stop_service1:
if(bound)
{
unbindService(connection);
bound = false;
}//解绑Service
break;
case R.id.show_random:
if(bound == true)
{
Toast.makeText(this, "number is :"+localService.getRandomNumber(), Toast.LENGTH_SHORT).show();
}
break;
}
} private ServiceConnection connection = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
LocalBinder binder = (LocalBinder)service; //得到service的IBinder对象
localService = binder.getService();//得到Service的引用,后续即可使用Service的方法
bound = true;
} @Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
bound = false;
} }; }
2. 使用Messenger
如果需要服务跟远程进程通信,那么就可以使用Messenger对象来给服务提供接口。
以下是信使(Messenger)对象的使用概要:
1. 服务端实现的一个处理器(Handler接口),这个处理器针对每次来自客户端的调用接收一次回调;
2. 这个处理器被用于创建一个信使对象(Messager)(这个信使对象要引用这个处理器);
3. 信使对象创建一个创建一个服务端从onBind()方法中返回给客户端的IBinder对象;
4. 客户端使用这个IBinder对象来实例化这个信使对象(信使引用了服务端的处理器),客户端使用这个信使给服务端发送Message对象;
5. 服务端在它的处理器(Handler)的handleMessage()方法中依次接收每个Message对象
在这种方法中,没有给客户端提供服务端的方法调用,相反,客户端会给发送服务端消息(Message)对象,服务端会在它的处理器中接受这些消息对象。
代码:
ServiceShow.java
package com.luoye.servicelearn; import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.widget.Toast; public class ServiceShow extends Service{ static final int MSG_CODE = 0x10;//message的消息类型定义 class IncomingHandler extends Handler //message处理器,应与信使绑定
{
public void handleMessage(Message msg)
{
switch(msg.what)
{
case MSG_CODE:
Toast.makeText(ServiceShow.this, "Hello world", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
//创建一个信使,该信使使用Handler对象作为msg的处理器
final Messenger messenger = new Messenger(new IncomingHandler()); @Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(ServiceShow.this, "Binding", Toast.LENGTH_SHORT).show();
return messenger.getBinder();//返回对应信使的Binder,返回给client使用
} }
MainActivity.java
package com.luoye.servicelearn; import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.view.Menu;
import android.view.View; public class MainActivity extends Activity { Messenger messenger;
boolean bound = false; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} public void buttonOnClickListener(View v)
{
switch(v.getId())
{
case R.id.start_service1:
Intent intent_start = new Intent(this, ServiceShow.class);
//绑定Service 第二个参数为ServiceConnection对象,由于bindService是异步的,
//bindService()方法立即返回并且不返回IBinder对象,所以需要在ServiceConnection的方法中去处理
//BIND_AUTO_CREATE表示if Service不存在,即onCreate()
bindService(intent_start, connection, Context.BIND_AUTO_CREATE);
if(bound)
{
//产生message对象
Message msg = Message.obtain(null, ServiceShow.MSG_CODE, 0, 0);
try
{
//使用client端的信使发送message,该消息会通过Binder对应的信使递交到Service端的
//信使,并由该端信使的消息处理器Handler进行处理
messenger.send(msg);
}
catch (Exception e)
{
e.printStackTrace();
}
}
break;
case R.id.stop_service1:
if(bound)
{
unbindService(connection);//解绑Service
bound = false;
}
break;
}
} private ServiceConnection connection = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
messenger = new Messenger(service); //利用Service返回的信使的对应的IBinder来创建client端的信使对象
bound = true;
} @Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
messenger = null;
bound = false;
} }; }
[Android学习笔记5]四大应用组件之一:Service 下的更多相关文章
- [Android学习笔记4]四大应用组件之一:Service 上
一.什么是Service 一个Service就是一个能够在后台执行长时操作的应用程序组件,并且不提供用户界面.一个应用程序组件能够启动一个Service,即使用户切换到另一个应用程序,这个Servic ...
- Android学习笔记(十七)——数据库操作(下)
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 这一次我们来试一试升级数据库,并进行数据库的CRUD操作,其中, C 代表添加(Create) ,R 代表查询 ...
- Android学习笔记(五一):服务Service(上)- IntentService
转自 http://blog.csdn.net/flowingflying/article/details/7616333 对于需要长期运行,例如播放音乐.长期和服务器的连接,即使已不是屏幕当前的ac ...
- Android学习笔记:使用ViewPager组件实现图片切换
在很多App中,尤其是第一次安装启动后,都会出现几个图片进行一些app的介绍和说明,图片可以随着滑动而切换. 我们这里利用 ViewPager组件来演示如何实现这一点. 1.创建一个app工程,默认创 ...
- Android学习笔记 ImageSwitcher图片切换组件的使用
activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...
- Android学习笔记 Toast屏幕提示组件的使用方法
activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...
- Android学习笔记(24):进度条组件ProgressBar及其子类
ProgressBar作为进度条组件使用,它还派生了SeekBar(拖动条)和RatingBar(星级评分条). ProgressBar支持的XML属性: Attribute Name Related ...
- Android学习笔记 TextSwitcher文本切换组件的使用
activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...
- 【转】 Pro Android学习笔记(七六):服务(1):local和remote
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ Android提供服务,服务是运行在后台的 ...
随机推荐
- Maven+SpringMVC+MyBatis 上传图片
上传文件我一直都觉得很难,好吧,所有涉及文件操作的我都觉得不容易.然后今天尝试了从网页上传图片保存到服务器.这个例子的前提是搭建好了服务器端框架:Maven+Spring MVC+MyBatis.当然 ...
- linux:如何修改用户的密码
1.首先,要用CRT软件连接Linux系统. 2.首选,确认是用root用户登录系统的. 输入命令: id ,查看登录用户信息. 3.若修改root自己的密码,直接输入 passwd . 输入两遍,新 ...
- RAW模板命名规范
国有国法,家有家规,任何一种开发都要有自己规范,RAW模板也一样,这个文章来介绍一下RAW模板命名的规范. 格式: 开发者或组织_描述词_名称 开发者或组织:如know或自己的组织名 描述词:c-&g ...
- python的内置函数bin()
bin(x) 中文说明:将整数x转换为二进制字符串,如果x不为Python中int类型,x必须包含方法__index__()并且返回值为integer: 参数x:整数或者包含__index__()方法 ...
- selenium 学习笔记 ---新手学习记录(5) 问题总结(java)
1.今天遇到个奇葩问题,iframe有两个id相同的(如下图) 使用driver.switchTo().frame(“frmLinkPage1”);这个无法使用了. 后来改用driver.switch ...
- 07-C语言流程控制if、switch
目录: 一.流程控制 条件分支 if else 二.流程控制 开关分支 switch 回到顶部 一.流程控制 条件分支 1.语法格式:if(表达式1){ //表达式1为真(非0时),执行的语句部分. ...
- hadoop配置及无法移动文件到hdfs故障解析
首先博主用的64位ubuntu,hadoop官方只提供32位版本,这样的话启动本地库无法兼容,需要自己编译为64位版本,或下载别人编译好的64位版本. 下载好需要在etc/hadoop目录下改动以下几 ...
- 使用Lock实现信号量
public class SemaphoreOnLock { private final Lock lock = new ReentrantLock(); private fi ...
- phpmyadmin出现空password登录被禁止
在Windows或者Linux下mysql安装后默认的password为空,又当我们又安装了mysql的管理工具 phpmyadmin后登陆时出现"空password登陆呗禁止(參见同意pa ...
- block 解析 - 局部变量
局部变量 block内使用局部变量,一般都是截获变量(只读),截获离block初始化最近的一次的值. 引用官方文档: Stack (non-static) variables local to the ...