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()是因为我连续点击了多次开启服务按钮)

   

  上图可以看出服务第一次开启时先是调用了onCreate()方法和onStartCommand()方法,多次点击开始服务时只调用了onStartCommand()方法

   so:

   onCreate()方法是服务创建的时候调用的~

   onStartCommand()方法在每次启动服务的时候都会调用~

   onDestory()方法在停止服务时候会调用~

   点击停止服务后,输出如图:

 

 启动服务还有一种方式是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();
		}
	};

}

  运行后点击绑定服务后输出如下:

     

     说明成功绑定了服务且传递了数据,点击解除绑定服务时候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的数量而更新):

    

   期间遇到的问题:

   bindService后无效,MyService类中的onBind()方法没有被调用

   解决:这种情况下你的Activity应该是继承了TabBarActivity,绑定服务的时候调用写这种形式:

   this.getApplicationContext().bindService(intent, mConnection, BIND_AUTO_CREATE);

   最近几天用到,总结一下,希望可以为大家带来帮助,有错误还请大神指正。

 

 

 

posted @ 2017-01-06 23:16  奋斗者—cyf  阅读(30164)  评论(1编辑  收藏  举报