Service组件
服务没有可视化接口,可以在后台运行。
生命周期:onCreate() ------->onStart(Intent intent , int startId)----------->onDestroy()
服务必须显示调用才可启动。
开机启动一个服务:
需要借助BroadCast监听开机事件,然后在onReceive()中启动服务。
启动服务的2中方法:context.startService() 和context.bindService()
1、context.startService()
此种方式启动service时会一次调用
context.startService() --------> onCreate()----->onStart()(service可被启动多次,如果service正在运行,则直接调用此方法)------>service running
context.stopService() --------> onDestroy()
2、context.bindService()
此种方式启动service时会一次调用
context.startService() --------> onCreate()----->onBind()(只可绑定一次)------>service running
context.stopService() --------> onUnbind()----->onDestroy()
onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的运行状态等。
此时调用者和Service绑定在一起,Context退出了,service就会调用相应的onUnbind()方法。
AIDL(Android Interface Definition Language)实现跨进程访问
AIDL(android接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。
要使用AIDL,Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务类。Service的实现类需要去继承这个stub服务类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:
service端进程:
首先建立一个android项目,并建立一个简单的AIDL服务(可看做一个接口),如下:
在包下建立一个aidl文件IService.aidl:
package com.service;
interface IService{
String getValue();
}写一个Service类,在类中定义一个内部类MyServiceImpl ,该类实现aidl文件对应的stub服务类,如下:
public class MyService extends Service{ private String text=""; @Override public IBinder onBind(Intent intent) { return new MyServiceImpl();//此处必须返回一个 IService的实现类 } public class MyServiceImpl extends IService.Stub{ @Override public String getValue() throws RemoteException { text = text +"io"; return text; } } }
在manifest文件中配置此service,如下:
<service android:name=".MyService">
<intent-filter >
<action android:name="com.service.serviceio"/>//此处是客户端用来访问AIDL服务的ID
</intent-filter>
</service>
调用服务的进程:
建立一个android项目作为客户端。
第一步:将service端项目生成的gen文件夹下的类(包括包)复制到调用服务的进程的src目录下。
第二步:写一个activity调用此服务:
package com.client; import com.service.IService; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class IClient extends Activity implements OnClickListener{ private IService iService =null; private Button bind,invoke; private TextView text; private ServiceConnection serviceConnection = 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 iService = IService.Stub.asInterface(service); invoke.setEnabled(true); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); bind = (Button)findViewById(R.id.bind); invoke = (Button)findViewById(R.id.invoke); invoke.setEnabled(false); bind.setOnClickListener(this); invoke.setOnClickListener(this); text = (TextView)findViewById(R.id.text); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()){ case R.id.bind: bindService(new Intent("com.service.serviceio"), serviceConnection, Context.BIND_AUTO_CREATE); break; case R.id.invoke: try { text.setText(iService.getValue()); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } break; } } }
此时就可实现访问service端的数据。
注意:AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据就需要进一步的处理。
AIDL服务支持的数据类型有:
java的简单类型:int char boolean 等
String 和CharSequence
List和Map;对象元素的类型也必须是AIDL服务支持的类型
AIDL自动生成的接口(需要import)
实现android.os.Parcelable接口的类(需要import)
研究中...