Android之服务(二)活动和服务进行通信
2016-01-27 15:39
501 查看
Android之服务(二)活动和服务进行通信
一,简介
我们学习了启动和停止服务的方法,不知道你有没有发现,虽然服务是在活
动里启动的,但在启动了服务之后,活动与服务基本就没有什么关系了。确实如此,我们在
活动里调用了 startService()方法来启动 MyService 这个服务,然后 MyService 的 onCreate()和
onStartCommand()方法就会得到执行。之后服务会一直处于运行状态,但具体运行的是什么
逻辑,活动就控制不了了。这就类似于活动通知了服务一下: “你可以启动了! ”然后服务就
去忙自己的事情了,但活动并不知道服务到底去做了什么事情,以及完成的如何。
那么有没有什么办法能让活动和服务的关系更紧密一些呢?例如在活动中指挥服务去
干什么,服务就去干什么。当然可以,这就需要借助我们刚刚忽略的 onBind()方法了。
比如说目前我们希望在 MyService 里提供一个下载功能,然后在活动中可以决定何时开
始下载, 以及随时查看下载进度。 实现这个功能的思路是创建一个专门的 Binder 对象来对下
载功能进行管理,修改 MyService 中的代码,如下所示:
public class MyService extends Service { private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder { public void startDownload() { Log.d("MyService", "startDownload executed"); } public int getProgress() { Log.d("MyService", "getProgress executed"); return 0; } } @Override public IBinder onBind(Intent intent) { return mBinder; } …… }
可以看到,这里我们新建了一个 DownloadBinder 类,并让它继承自 Binder,然后在它
的内部提供了开始下载以及查看下载进度的方法。当然这只是两个模拟方法,并没有实现真
正的功能,我们在这两个方法中分别打印了一行日志。
接着,在 MyService 中创建了 DownloadBinder 的实例,然后在 onBind()方法里返回了这
个实例,这样 MyService 中的工作就全部完成了。
下面就要看一看,在活动中如何去调用服务里的这些方法了。首先需要在布局文件里新
增两个按钮,修改 activity_main.xml 中的代码,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > …… <Button android:id="@+id/bind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Bind Service" /> <Button android:id="@+id/unbind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Unbind Service" /> </LinearLayout>
这两个按钮分别是用于绑定服务和取消绑定服务的, 那到底谁需要去和服务绑定呢?当
然就是活动了。 当一个活动和服务绑定了之后, 就可以调用该服务里的 Binder提供的方法了。
修改 MainActivity 中的代码,如下所示:
public class MainActivity extends Activity implements OnClickListener { private Button startService; private Button stopService; private Button bindService; private Button unbindService; private MyService.DownloadBinder downloadBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { downloadBinder = (MyService.DownloadBinder) service; downloadBinder.startDownload(); downloadBinder.getProgress(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); …… bindService = (Button) findViewById(R.id.bind_service); unbindService = (Button) findViewById(R.id.unbind_service); bindService.setOnClickListener(this); unbindService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { …… case R.id.bind_service: Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE); // 绑定服务 break; case R.id.unbind_service: unbindService(connection); // 解绑服务 break; default: break; } } }
可以看到,这里我们首先创建了一个 ServiceConnection 的匿名类,在里面重写了
onServiceConnected()方法和 onServiceDisconnected()方法,这两个方法分别会在活动与服务
成功绑定以及解除绑定的时候调用。在 onServiceConnected()方法中,我们又通过向下转型
得到了 DownloadBinder 的实例,有了这个实例,活动和服务之间的关系就变得非常紧密了。
现在我们可以在活动中根据具体的场景来调用 DownloadBinder 中的任何 public 方法,即实
现了指挥服务干什么,服务就去干什么的功能。这里仍然只是做了个简单的测试,在
onServiceConnected()方法中调用了 DownloadBinder的 startDownload()和 getProgress()方法。
当然,现在活动和服务其实还没进行绑定呢,这个功能是在 Bind Service 按钮的点击事
件里完成的。可以看到,这里我们仍然是构建出了一个 Intent 对象,然后调用 bindService()
方法将 MainActivity 和 MyService 进行绑定。 bindService()方法接收三个参数, 第一个参数就
是刚刚构建出的 Intent 对象,第二个参数是前面创建出的 ServiceConnection 的实例,第三个
参数则是一个标志位,这里传入 BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动
创建服务。这会使得 MyService 中的 onCreate()方法得到执行,但 onStartCommand()方法不
会执行。
然后如果我们想解除活动和服务之间的绑定该怎么办呢?调用一下 unbindService()方法
就可以了,这也是 Unbind Service 按钮的点击事件里实现的功能。
现在让我们重新运行一下程序吧,界面如图所示。
点击一下 Bind Service 按钮,然后观察 LogCat 中的打印日志如图所示:
可以看到,首先是 MyService 的 onCreate()方法得到了执行,然后 startDownload()和
getProgress()方法都得到了执行, 说明我们确实已经在活动里成功调用了服务里提供的方法了。
另外需要注意,任何一个服务在整个应用程序范围内都是通用的,即 MyService 不仅可
以和 MainActivity 绑定,还可以和任何一个其他的活动进行绑定,而且在绑定完成后它们都
可以获取到相同的 DownloadBinder 实例。
相关文章推荐
- Android注解式开发BufferKnife的使用
- android 验证码 (canvas)
- 控制输入法软键盘隐藏
- Android框架模式(1)-MVP入门
- Android 手写Binder 教你理解android中的进程间通信
- Android traces.txt只保留最后一次发生ANR时的traces信息,那么以前的traces信息就丢失了么?
- 讨论一个Android 异步开发中容易忽视的bug
- Android之服务
- Android camera2预览界面流程
- Android内存泄漏简介
- 转载Android中全屏或者取消标题栏
- Android:我为何要封装DialogFragment?
- Android之使用 AsyncTask
- Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解
- Android之Service与IntentService的比较
- Android之异步消息处理机制
- Android Timer 定时器 与handler的配合
- [Android Pro] 使用apktool工具遇到could not decode arsc file的解决办法
- Android之多线程编程
- 五步搞定Android开发环境部署——非常详细的Android开发环境搭建教程