Android笔记二(service)

1、Service的基本用法

首先看一下如何在项目中定义一个服务,在这个项目中新增一个名为 MyService 的类,并让它继承自 Service。这样的话一个服务就定义好了。既然是定义一个服务,自然应该在服务中去处理一些事情了,那处理事情的逻辑应该写在哪里呢?这时就可以重写 Service 中的另外一些方法。OnCreate()、onStartCommand()、onDestory()。这三个方法是最常用的方法。其中 onCreate()方法会在服务创建的时候调用,onStartCommand()方法会在每次服务启动的时候调用,onDestroy()方法会在服务销毁的时候调用。
通常情况下,如果我们希望服务一旦启动就立刻去执行某个动作,就可以将逻辑写在onStartCommand()方法里。而当服务销毁时,我们又应该在 onDestroy()方法中去回收那些不再使用的资源。

public class Myservice extends Service {
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Log.v("msg", "--onBind()--方法被调用");
		return null;
	}
	// onCreate()方法会在服务创建的时候调用
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		Log.v("msg", "--onCreate()--方法被调用");
	}
	//onStartCommand()方法会在每次服务启动的时候调用
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		Log.v("msg", "--onStartCommand()--方法被调用");
		return super.onStartCommand(intent, flags, startId);
	}
	//onDestroy()方法会在服务销毁的时候调用
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.v("msg", "--onDestroy()--方法被调用");
	}

}
另外需要注意,每一个服务都需要在 AndroidManifest.xml文件中进行注册才能生效。

 <service android:name="com.test.testservice.Myservice"></service>
以上操作一个服务就定义好了,接下来去MainActivity中去启动和停止这个服务

public class MainActivity extends Activity {
	private Button btn1;
	private Button btn2;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn1 = (Button) findViewById(R.id.btn_01);
		btn2 = (Button) findViewById(R.id.btn_02);
		btn1.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//创建一个Intent对象,用来启动服务
				Intent stratIntent = new Intent(MainActivity.this,
						Myservice.class);
				//启动服务
				startService(stratIntent);
			}
		});
		btn2.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//创建一个Intent对象,用来停止服务
				Intent stopIntent = new Intent(MainActivity.this,
						Myservice.class);
				//停止服务
				stopService(stopIntent);
			}
		});
	}

}
  按钮的点击事件里,我们构建出了一个 Intent 对象,并调用 startService()方法来启动 MyService 这个服务。在 Stop Serivce 按钮的点击事件里, 我们同样构建出了一个Intent对象, 并调用stopService()方法来停止MyService这个服务。不用Activity去控制服务,只需要在 MyService 的任何一个位置调用 stopSelf()方法也能让这个服务停止下来了。

2、服务和活动的基本通信
为了让活动和服务之间进行基本的通信,而不是活动发出一个命令之后就不能去控制服务怎么运行,就需要使用到Service中的onBind()方法。

比如说目前我们希望在 MyService 里提供一个下载功能,然后在活动中可以决定何时开始下载, 以及随时查看停止下载。 实现这个功能的思路是创建一个专门的 Binder 对象来对下载功能进行管理

public class Myservice extends Service {
	//实例化MyBinder类
	private MyBinder myBinder = new MyBinder();
	//创建MyBinder类,继承Binder,在这里面写activity要service做的事,例如方法startDownload()和stopDownload()
	class MyBinder extends Binder{
		public void startDownload() {
			// TODO Auto-generated method stub
			Log.v("msg", "开始下载!");
		}
		public void stopDownload() {
			// TODO Auto-generated method stub
			Log.v("msg", "停止下载!");
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Log.v("msg", "--onBind()--方法被调用");
		//当Activity要控制Service时返回MyBinder实例,否则返回null
		return myBinder;
	}
	// onCreate()方法会在服务创建的时候调用
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		Log.v("msg", "--onCreate()--方法被调用");
	}
	//onStartCommand()方法会在每次服务启动的时候调用
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		Log.v("msg", "--onStartCommand()--方法被调用");
		return super.onStartCommand(intent, flags, startId);
	}
可以看到,这里我们新建了一个 DownloadBinder 类,并让它继承自 Binder,然后在它的内部提供了开始下载以及查看下载进度的方法。当然这只是两个模拟方法,并没有实现真正的功能,我们在这两个方法中分别打印了一行日志。接着,在 MyService 中创建了 DownloadBinder 的实例,然后在 onBind()方法里返回了这个实例,这样 MyService 中的工作就全部完成了。

public class MainActivity extends Activity {
	private Button btn3;
	private Button btn4;

	private Myservice.MyBinder myBinder;
	//创建一个 ServiceConnection 的匿名类,在里面重写了onServiceConnected()方法和 onServiceDisconnected()方法
	private ServiceConnection connection = new ServiceConnection() {
		//当activity和service取消绑定时调用
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			Log.v("msg", "服务断开连接");
		}
		//当activity和service成功绑定时调用
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			Log.v("msg", "服务连接");
			//向下转型,得到MyBinder实例
			myBinder = (MyBinder) service;
			//调用MyBinder中的startDownload()方法
			myBinder.startDownload();
			//调用MyBinder中的stopDownload()方法
			myBinder.stopDownload();

		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn3 = (Button) findViewById(R.id.btn_03);
		btn4 = (Button) findViewById(R.id.btn_04);

		btn3.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//创建Intent对象,用来绑定Service bindService()方法接收三个参数, 第一个参数就
				//是刚刚构建出的 Intent 对象,第二个参数是前面创建出的 ServiceConnection 的实例,第三个
				//参数则是一个标志位,这里传入 BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务
				Intent bindIntent = new Intent(MainActivity.this,
						Myservice.class);
				//绑定service
				bindService(bindIntent, connection, BIND_AUTO_CREATE);
			}
		});
		btn4.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				//解除Activity和Service的绑定
				unbindService(connection);
			}
		});
	}

}
可以看到,这里我们首先创建了一个 ServiceConnection 的匿名类,在里面重写了onServiceConnected()方法和 onServiceDisconnected()方法,这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用。在 onServiceConnected()方法中,我们又通过向下转型得到了 DownloadBinder 的实例,有了这个实例,活动和服务之间的关系就变得非常紧密了。现在我们可以在活动中根据具体的场景来调用 DownloadBinder 中的任何 public 方法,即实现了指挥服务干什么,服务就去干什么的功能。这里仍然只是做了个简单的测试,在onServiceConnected()方法中调用了 DownloadBinder的 startDownload()和 stopDownload()方法。当然,现在活动和服务其实还没进行绑定呢,这个功能是在 Bind Service 按钮的点击事件里完成的。可以看到,这里我们仍然是构建出了一个 Intent 对象,然后调用 bindService()方法将 MainActivity 和 MyService 进行绑定。bindService()方法接收三个参数, 第一个参数就是刚刚构建出的 Intent 对象,第二个参数是前面创建出的 ServiceConnection 的实例,第三个参数则是一个标志位,这里传入 BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务。这会使得 MyService 中的 onCreate()方法得到执行,但 onStartCommand()方法不会执行。然后如果我们想解除活动和服务之间的绑定该怎么办呢?调用一下 unbindService()方法就可以了,这也是 Unbind Service 按钮的点击事件里实现的功能。

3、使用前台服务
前台服务的使用是为了防止系统内存不足时,关闭后台的服务。

前台服务使用只需要在MyService的方法onCreate()中加入如下代码即可

//下面代码是使用前台服务,防止服务在系统内存不足时被回收
		Notification notification = new Notification(R.drawable.ic_launcher,"Notification comes", System. currentTimeMillis());
		Intent notificationIntent = new Intent(this, MainActivity.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent, 0);
		notification.setLatestEventInfo(this, "This is title", "This is content", pendingIntent);
		startForeground(1, notification);




4、使用IntentService

为了防止程序在servcie中进行耗时操作,出现AND异常,可以使用IntentService来代替Service,这里面开启了子线程,可以用来进行耗时的操作。

public class MyIntentService extends IntentService {
	public MyIntentService() {
		// TODO Auto-generated constructor stub
		super("MyIntentService");
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		// TODO Auto-generated method stub
		//在这里处理具体的逻辑问题,不用担心ANR,这是一个子线程,事情做完会自动调用onDestroy()方法
		Log.v("msg","Thread id is " + Thread.currentThread().getId());
	}
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.v("msg", "--onDestroy()--方法被调用");
	}
}
这里首先是要提供一个无参的构造函数,并且必须在其内部调用父类的有参构造函数。然后要在子类中去实现 onHandleIntent()这个抽象方法, 在这个方法中可以去处理一些具体的逻辑,而且不用担心 ANR 的问题,因为这个方法已经是在子线程中运行的了。这里为了证实一下, 我们在 onHandleIntent()方法中打印了当前线程的 id。 另外根据 IntentService 的特性,这个服务在运行结束后应该是会自动停止的,所以我们又重写了 onDestroy()方法,在这里也打印了一行日志,以证实服务是不是停止掉了。

在 AndroidManifest.xml文件中进行注册才能生效。

<service android:name="com.test.testservice.MyIntentService"></service>
看看MainActivity中的代码,与Service的使用并没什么区别

public class MainActivity extends Activity {

	private Button btn5;


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		btn5 = (Button) findViewById(R.id.btn_05);

		btn5.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				//  打印主线程的id
				Log.v("msg", "Thread id is " + Thread.currentThread().getId());
				//创建一个Intent对象
				Intent intentService = new Intent(MainActivity.this, MyIntentService.class);
				//开启服务
				startService(intentService);
			}
		});
	}

}


以上代码布局非常简单,就不给出

这些乃是作者看《第一行代码》的笔记。另官方service介绍的链接:点击打开链接





发布了23 篇原创文章 · 获赞 19 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章