Android—Service与Activity的交互

欠伸展肢体,吟咏心自愉。这篇文章主要讲述Android—Service与Activity的交互相关的知识,希望能为你提供帮助。
    service—android的四大组件之一。人称“后台服务”指其本身的运行并不依赖于用户可视的UI界面
    实际开发中我们经常需要service和activity之间可以相互传递数据维持程序的运行。
    先了解Service的生命周期吧。
新建一个类继Service:

package com.example.myservicedemo.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; /** * 服务类(需要在项目清单文件中注册服务) * * @author lenovo * */ public class MyService extends Service { @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } /** * 服务创建的时候调用 */ @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); System.out.println("=========onCreate======"); } /** * 服务启动的时候调用 */ @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub System.out.println("=========onStartCommand======"); return super.onStartCommand(intent, flags, startId); } /** * 服务销毁的时候调用 */ @Override public void onDestroy() { // TODO Auto-generated method stub System.out.println("=========onDestroy======"); super.onDestroy(); } }

  新建以上类并继承Service后只会重写onBind()方法,其他方法是我手动手写,为了弄清楚Service的生命周期
  MainActivity中(设置两个按钮用来开始和停止服务):
package com.example.myservicedemo.ui; import com.example.myservicedemo.R; import com.example.myservicedemo.service.MyService; import com.example.myservicedemo.service.MyService.DownLoadBinder; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_start = (Button) findViewById(R.id.btn_start); Button btn_stop = (Button) findViewById(R.id.btn_stop); btn_start.setOnClickListener(this); btn_stop.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub int id = v.getId(); switch (id) { /* * 开启服务点击事件 */ case R.id.btn_start: Intent startIntent = new Intent(this, MyService.class); startService(startIntent); break; /* * 停止服务点击事件 */ case R.id.btn_stop: Intent stopIntent = new Intent(this, MyService.class); stopService(stopIntent); break; default: break; } }}

切记android中的服务是需要在项目清单文件中注册的(AndroidStudio可以自动,eclipse需要手动添加):
        < service android:name="服务类坐所在的包名.MyService"> < /service>
      此时运行程序,点击开启服务时候输出是下图:(我输出多次onStartCommand()是因为我连续点击了多次开启服务按钮)
   
Android—Service与Activity的交互

文章图片

  上图可以看出服务第一次开启时先是调用了onCreate()方法和onStartCommand()方法,多次点击开始服务时只调用了onStartCommand()方法
    so:
    onCreate()方法是服务创建的时候调用的~
    onStartCommand()方法在每次启动服务的时候都会调用~
    onDestory()方法在停止服务时候会调用~
    点击停止服务后,输出如图:
 
Android—Service与Activity的交互

文章图片

  启动服务还有一种方式是bindService();
  此时的MyService类要做改变:
package com.example.myservicedemo.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; /** * 服务类(需要在项目清单文件中注册服务) * * @author lenovo * */ public class MyService extends Service { private DownLoadBinder downLoadBinder=new DownLoadBinder(); @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub System.out.println("=====onBind====="); return downLoadBinder; } /** * 内部类继承Binder * @author lenovo * */ public class DownLoadBinder extends Binder{ public void startDownLoad(){ System.out.println("=====startDownLoad()====="); } public void getProgress(){ System.out.println("=====getProgress()====="); } } /** * 服务创建的时候调用 */ @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); System.out.println("=========onCreate======"); } /** * 服务启动的时候调用 */ @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub System.out.println("=========onStartCommand======"); return super.onStartCommand(intent, flags, startId); } /** * 服务销毁的时候调用 */ @Override public void onDestroy() { // TODO Auto-generated method stub System.out.println("=========onDestroy======"); super.onDestroy(); } }

以上的代码和第一次相比,一是多了一个内部类DownLoadBinder继承IBinder并且声明了两个方法,二是将onBind方法的返回值改为了DownLoadBinder类型的变量
      activity bindService方法启动服务时候一般是需要传递数据的,核心就在onBind()方法中,往下看
  MainActivity中加两个按钮:绑定服务和取消绑定服务
   
package com.example.myservicedemo.ui; import com.example.myservicedemo.R; import com.example.myservicedemo.service.MyService; import com.example.myservicedemo.service.MyService.DownLoadBinder; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { private MyService.DownLoadBinder downLoadBinder; private MyService myService; //我们自己的service @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_start = (Button) findViewById(R.id.btn_start); Button btn_stop = (Button) findViewById(R.id.btn_stop); Button btn_bind = (Button) findViewById(R.id.btn_bind); Button btn_unbind = (Button) findViewById(R.id.btn_unbind); btn_start.setOnClickListener(this); btn_stop.setOnClickListener(this); btn_bind.setOnClickListener(this); btn_unbind.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub int id = v.getId(); switch (id) { /* * 开启服务点击事件 */ case R.id.btn_start: Intent startIntent = new Intent(this, MyService.class); startService(startIntent); break; /* * 停止服务点击事件 */ case R.id.btn_stop: Intent stopIntent = new Intent(this, MyService.class); stopService(stopIntent); break; /* * 绑定服务点击事件 */ case R.id.btn_bind: Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE); break; /* * 解除绑定服务点击事件 */ case R.id.btn_unbind: unbindService(connection); break; default: break; } } private ServiceConnection connection=new ServiceConnection() { /** * 服务解除绑定时候调用 */ @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub} /** * 绑定服务的时候调用 */ @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub //myService=((DownLoadBinder) service). downLoadBinder=(DownLoadBinder) service; /* * 调用DownLoadBinder的方法实现参数的传递 */ downLoadBinder.startDownLoad(); downLoadBinder.getProgress(); } }; }

运行后点击绑定服务后输出如下:
     
Android—Service与Activity的交互

文章图片

      说明成功绑定了服务且传递了数据,点击解除绑定服务时候ondestory()方法输出
    不过这种方法好像只能传递一次数据,,,,不爽,,,,比如后台在实时更新东西,activity需要实时获取呢???
    查找资料大多是以下几种方式:
    1.使用接口回调方式,activity实现相应的接口,service通过接口进行回调,比较灵活
    2.使用广播
    这篇博客主要介绍第一种方法,为什么不介绍第二种???——不愿意介绍,不喜欢。
    使用接口回调方式的MyService和MainActivity代码我是备注详细之后才粘贴的,大家可以看注释
    MyService代码:
     
package com.example.myservicedemo.service; import java.util.Timer; import java.util.TimerTask; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; /** * 服务类(需要在项目清单文件中注册服务) * * @author lenovo * */ public class MyService extends Service { private DownLoadBinder downLoadBinder=new DownLoadBinder(); /** * 回调 */ private Callback callback; /** * Timer实时更新数据的 */ private Timer mTimer=new Timer(); /** * */ private int num; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub System.out.println("=====onBind====="); return downLoadBinder; } /** * 内部类继承Binder * @author lenovo * */ public class DownLoadBinder extends Binder{ /** * 声明方法返回值是MyService本身 * @return */ public MyService getService() { return MyService.this; } } /** * 服务创建的时候调用 */ @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); /* * 执行Timer 2000毫秒后执行,5000毫秒执行一次 */ mTimer.schedule(task, 0, 1000); } /** * 提供接口回调方法 * @param callback */ public void setCallback(Callback callback) { this.callback = callback; } /** * */ TimerTask task = new TimerTask(){@Override public void run() { // TODO Auto-generated method stub num++; if(callback!=null){ /* * 得到最新数据 */ callback.getNum(num); }} }; /** * 回调接口 * * @author lenovo * */ public static interface Callback { /** * 得到实时更新的数据 * * @return */ void getNum(int num); } /** * 服务销毁的时候调用 */ @Override public void onDestroy() { // TODO Auto-generated method stub System.out.println("=========onDestroy======"); /** * 停止Timer */ mTimer.cancel(); super.onDestroy(); } }

MainActivity代码:
package com.example.myservicedemo.ui; import com.example.myservicedemo.R; import com.example.myservicedemo.service.MyService; import com.example.myservicedemo.service.MyService.Callback; import com.example.myservicedemo.service.MyService.DownLoadBinder; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { private MyService.DownLoadBinder downLoadBinder; // private MyService myService; //我们自己的service @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_start = (Button) findViewById(R.id.btn_start); Button btn_stop = (Button) findViewById(R.id.btn_stop); Button btn_bind = (Button) findViewById(R.id.btn_bind); Button btn_unbind = (Button) findViewById(R.id.btn_unbind); btn_start.setOnClickListener(this); btn_stop.setOnClickListener(this); btn_bind.setOnClickListener(this); btn_unbind.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub int id = v.getId(); switch (id) { /* * 开启服务点击事件 */ case R.id.btn_start: Intent startIntent = new Intent(this, MyService.class); startService(startIntent); break; /* * 停止服务点击事件 */ case R.id.btn_stop: Intent stopIntent = new Intent(this, MyService.class); stopService(stopIntent); break; /* * 绑定服务点击事件 */ case R.id.btn_bind: Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE); break; /* * 解除绑定服务点击事件 */ case R.id.btn_unbind: unbindService(connection); break; default: break; } } private ServiceConnection connection=new ServiceConnection() { /** * 服务解除绑定时候调用 */ @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub} /** * 绑定服务的时候调用 */ @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub downLoadBinder = (DownLoadBinder) service; MyService service2 = downLoadBinder.getService(); /** * 实现回调,得到实时刷新的数据 */ service2.setCallback(new Callback() {@Override public void getNum(int num) { // TODO Auto-generated method stub System.out.println("====num===="+num); } }); } }; }

运行后的结果应该输出如图就对了(输出随service中num的数量而更新):
     
Android—Service与Activity的交互

文章图片

    期间遇到的问题:
    bindService后无效,MyService类中的onBind()方法没有被调用
    解决:这种情况下你的Activity应该是继承了TabBarActivity,绑定服务的时候调用写这种形式:
    this.getApplicationContext().bindService(intent, mConnection, BIND_AUTO_CREATE);
    最近几天用到,总结一下,希望可以为大家带来帮助,有错误还请大神指正。
 
 
【Android—Service与Activity的交互】 

    推荐阅读