Service组件笔记
Service简单介绍
- Service是Android四大组件之一,与Activity相似
- Service是在后台运行的,没有用户界面
- 不与用户进行交互的操作应该考虑用Service
- Android系统本身提供了大量的Service组件
创建一个Service
- 创建一个继承于Service的子类ServiceText.java
public class ServiceText extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
2.在清单文件AndroidManifest.xml中application标签里配置
<service android:name=".ServiceText">
<intent-filter>
<action android:name="com.jiaji.servicetext.MY_SERVICE"/>
</intent-filter>
</service>
启动、停止Service
在ServiceText.java中覆写三个方法便于观察Service运行周期
- onCreate
- onStartCommand
- onDestroy
@Override
public void onCreate() {
super.onCreate();
Log.i("myout", "service is created");
}
@Override
public int
onStartCommand(Intent intent, int flags, int startId) {
Log.i("myout", "start running");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i("myout", "onDestroy is running");
}
在布局文件中添加了启动和关闭Service的按钮
布局如图:
在MainActivity.java中启动和关闭
- startService启动服务
- stopService停止服务
public class MainActivity extends AppCompatActivity {
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent("com.jiaji.servicetext.MY_SERVICE");
}
public void startServiceClick(View view)
{
startService(intent);
}
public void stopServiceClick(View view)
{
stopService(intent);
}
}
结果
当点击启动时logcat打印出:
11-12 12:46:02.930 921-921/? I/myout: service is created
11-12 12:46:02.960 921-921/? I/myout: start running
当重复点击启动启动服务时
11-12 12:46:08.150 921-921/? I/myout: start running
11-12 12:46:08.480 921-921/? I/myout: start running
点击关闭服务时
11-12 12:47:29.956 921-921/? I/myout: onDestroy is running
结论:
当启动Service时,会创建一次服务,之后再启动服务时不会再次创建服务,会直接启动服务
当关闭服务时服务被销毁
IntentService一个继承于Service并处理异步请求的类
- 只执行一次,并会自动停止
- 可以启动多次
- 可以处理耗时操作,因为内部有一个工作线程
- 每个耗时操作以工作队列的方式在onHandleIntent执行
- 在构造方法中为线程取名
绑定、解绑服务
- 客户端调用bindService()方法绑定服务
- 绑定后服务onBind()方法返回一个IBinder对象
- 参数三:int flags(绑定服务的操作一般为:Context.BIND_AUTO_CERATE,如果没有创建就创建绑定)
- ServiceConnection实例来接收IBinder对象
- 注意广播接收器不能绑定服务
- unbindService()方法断开与服务器的链接
- -
通信的方式几种方式
在Service中创建一个继承Binder的内部类
- 同一进程中的简单通讯方式
- 当客户端绑定服务时,服务向客户端返回一个自定义的继承于Binder类的实例
- 然后客户端在ServiceConnection实例的onServiceConnected方法中获取服务返回的对象
IPC(interprocess communication)进程间通讯
- 不同进程组件间通讯需要使用IPC机制
- 可实现远程间通讯
AIDL(Android Interface Definition Language)安卓接口定义语言
- 支持类型:基本数据类型、String、CharSequence、List<String>、Map、自定义数据类型(自定义类型需要实现序列化接口、创建一个aidl文件来声明,格式如:package com.jiaji.musicplayer;
parcelable Person;
、在使用时注意添加上包名.自定义类名,才能找到类型)。 - 创建一个aidl文件,添加需要实现的方法(不能使用修饰符,格式和接口一样)
- 自动会生成一个接口,eclipse目录:gen;android studio目录:app\build\generated\source\aidl\debug\,接口总有一个Stub类(需要继承),里面有个proxy的代理内部类(不同进程、远程通信时调用)
- 创建一个继承于上一步中Stub的实现类类并覆写其中的抽象方法(就是aidl中添加的方法)
- 在Service的onbind()方法中返回上一步的实例
- 在客户端ServiceConnection的实例的onServiceConnected(ComponenName name, Ibinder service)方法中获取对象:3.Stub.asInterface(service);(3表示第三步自动生成的接口)
- 现在可以在客户可以调用实现的方法了
Messenger
实现IPC通信,底层也是使用的AIDL方式
与AIDL不同之处:Messenger方式是利用Handler形式处理,因此是线程安全的;而AIDL方式是非线程安全的
-以下是googel android开发文档中的详细使用代码:
1、 在Service中
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
String info = (String)msg.obj;
Toast.makeText(getApplicationContext(), "hello!" + info, Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
2、 在activity中
public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
msg.obj = ”传到service的对象”;
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
我的感受
- service说是个后台运行的操作,不与用户交互,当时我想启动线程不一样的吗?后来才反应过来service有自己的生命周期嘛,只要不异常中断和刻意中断,service可以长时间的对数据和操作进行管理,启动后不会受到Activity的生命周期的影响。
- startService启动的服务会长期存在,bindService启动的服务通常在解绑时停止,所以说有个使用技巧:先startService,后bindService,解绑时就不会停止服务
- 如果在清单文件service标签中加入android:process=”:xxx”单独启动一个进程来完成
想说的话
- 第一次写博客,不管怎么样,今后打算学习了新的东西就在这里记录一下,以便今后回顾,也希望小小笔记能帮助你们
- 如果内容有什么地方不对,求喷我,希望大家能一起学习和成长,谢谢大家。