Service是一个不提供用户交互的可以在后台长期执行操作的应用程序组件。其它的应用程序组件可以启动Service,当切换到其他应用程序,该service会在后台继续运行。其他组件也可以绑定到service与其交互,甚至可以执行进程间通信。
startService()
启动一个Service后,它就处于“开始状态”。一旦处于“开始状态”,一个Service可以无限期地在后台运行,甚至当启动它的组件已经被销毁。通常,一个“开始状态”的Service会执行一个单独的操作,不会返回结果给调用者。例如,通过网络上传或下载文件。当操作完成,这个Service应该停止它自己。bindService()
绑定到一个Service,则它处于“绑定状态”。处于“绑定状态”的Service提供了client-server接口,其允许这些组件可以与该Service执行诸如发送请求,获取结果,进程间通信等交互。一个处于“绑定状态”的Service仅和绑定到的应用程序组件运行一样长的时间。多个组件可以每个绑定到该Service一次,但当所有这些组件与该Service解绑后,该Service才会被销毁。注意:你的Service可以同时工作在两种形式。
像其他应用程序组件一样,所有的Service必须在manifest中进行声明。
<manifest ... >
...
<application ... >
<service android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:isolatedProcess=["true" | "false"]
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
. . .
</service>
...
</application>
</manifest>
android:name
属性是唯一必须的属性,它具体了Service的类名。一旦发布了应用程序,你不应该再更改这个名字,如果更改,可能导致代码出错,因为你的代码依赖明确的intents去启动或绑定到Service。android:enabled
<application>
元素也有enabled
属性,它作用于所有的应用程序组件。android:exported
android:icon
设置代表该Service的一个图标。如果没有设置则使用 <application>
元素设置的icon
属性。
android:isolatedProcess
该属性设置为“true”,则该Service会在一个特殊的进程下运行,该进程与其他系统进程分开,且没有自己的权限。与其通信的唯一方式就是通过Service API。
android:label
一个展示给用户的Service名字。如果没有设置则使用 <application>
元素设置的label
属性。
android:name
android:exported="false"
)。android:permission
startService()
, bindService()
,或stopService()
的调用者没有被授予这个权限,则这些方法不能起效并且Intent对象不能传递到该Service。<application>
元素设置的permission
属性。如果都没有设置,则该Service不受任何权限保护。android:process
<application>
元素的process
属性能为所有的组件设置不同的默认名字。各组件可以用它们自己的process
属性覆盖这个默认值,这允许你将你的应用分为几个进程。 Service的生命周期和activity的生命周期相似,但更简单。然而,要更关注Service的创建和销毁,因为Service运行在后台不能被用户注意到。
Service的生命周期可以追寻两种不同的路径:
startService()
方法时,该Service被创建。该Service会无限期地运行,可以调用stopSelf()
方法终止它。启动它的组件,也可以调用stopService()
方法来终止该Service。当该Service停止,系统就会销毁它…bindService()
方法时,该Service被创建。接下来该client可以通过IBinder
接口与该Service通信。该Service能够调用unbindService()
方法关闭连接。多个clients可以绑定到同一个Service,当所有它们解绑,系统可以销毁该Service。(该Service不需要终止它自己) startService()
方法启动Service后,还可以绑定到该Service。例如,一个后台音乐Service可以先通过调用startService()
方法启动播放音乐。之后,当用户可能需要对播放器进行控制或想获取当前播放歌曲信息的时候,一个activity可以通过调用bindService()
方法绑定到该Service。在这种情况下,调用stopService()
或stopSelf()
方法不能终止该Service,直到所以的clients与该Service解绑。public class ExampleService extends Service {
private static final String NAME = ExampleService.class.getSimpleName();
private static final String TAG = "sxd";
int mStartMode; //指明该Service被杀死后的行为表现
IBinder mBinder; //clients绑定接口
boolean mAllowRebind; //指明onRebind是否应该被使用
@Override
public void onCreate() {
//该Service被首次创建时调用
Log.i(TAG, NAME + "--onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, NAME + "--onStartCommand");
//该Service正在运行,client再次调用startService()时调用
return mStartMode;
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, NAME + "--onBind");
//client调用bindService()绑定到该Service时调用
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, NAME + "--onUnbind");
//所有已绑定到该Service的client调用unbindService()与该Service解绑时调用
return mAllowRebind;
}
@Override
public void onRebind(Intent intent) {
Log.i(TAG, NAME + "--onRebind");
//当onUnbind()被调用后,又有新的client调用bindService()来绑定该Service时调用
}
@Override
public void onDestroy() {
Log.i(TAG, NAME + "--onDestroy");
//该Service不再使用,销毁时调用
}
}
注意:不像activity的生命周期回调方法,你不被要求去调用这些回调方法的父类实现。
图:左侧展示了调用startService()
方法创建的Service的生命周期,右侧展示了调用bindService()
方法创建的Service的生命周期。
当一个Service从所有的clients解绑,系统就会销毁它(除非它也调用了onStartCommand()
方法启动)。如果一个Service是一个纯净的”绑定状态”Service,则你不需要管理它的生命周期-Android系统基于是否还绑定了其他clients来管理它。
然而,如果你选择实现onStartCommand()
回调方法,那么你必须明确地终止该Service,因为这个Service被考虑为”开始状态”Service。这种情况下,该Service运行直到调用了stopSelf()
或stopService()
方法,不管它是否绑定了其他clients。
如果你的Service处于”开始状态”且接受绑定,如果你想在下次client绑定到该Service时,收到onRebind()
方法回调,则当系统调用onUnbind()
方法时,应该返回true。onRebind()
方法返回void,但该client仍会在onServiceConnected()
方法中收到IBinder
。下面是这种逻辑的生命周期图解:
当在manifest中使用<service>
标签声明Service时,可以施加该Service的全局访问权限。这样做,其他应用需要在它们自己的manifest中声明相应的<uses-permission>
元素以能够启动,终止或绑定到该Service。
GINGERBREAD
(Android 2.3)中,当使用Context.startService(Intent)
时,你能够在Intent中设置Intent.FLAG_GRANT_READ_URI_PERMISSION
或Intent.FLAG_GRANT_WRITE_URI_PERMISSION
。这可以授予该Service对在Intent中的特定URIs临时的访问权限。访问持续到该Service调用了stopSelf(int)
方法或直到该Service被完全终止。该方式对其他没有请求受保护Service权限的应用或该Service完全没有暴露的授权访问同样有用。
一个Service通过权限保护独立IPC对它的调用。通过在执行这个调用之前调用checkCallingPermission(String)
方法检测是否具有访问权限。
一个Service已经启动或有clients绑定到它,则系统会尝试保持该Service的宿主进程。当运行在低内存状态需要杀死已存在进程时,下面情况的Service宿主进程具有较高的优先级:
onCreate()
, onStartCommand()
或onDestroy()
方法中执行代码,则该宿主进程被作为前台进程以确保代码执行而不被杀掉。BIND_ABOVE_CLIENT
,BIND_ALLOW_OOM_MANAGEMENT
, BIND_WAIVE_PRIORITY
,BIND_IMPORTANT
和BIND_ADJUST_WITH_ACTIVITY
来调整。startForeground(int, Notification)
方法将该Service设置为前台状态,这种情况下,系统认为它是用户可以感知到的,因此在低内存状态不会被作为杀掉的候选(理论上,该Service还是会在面对前台应用对内存的极度要求的压力下被杀死,但这是可以不用关心的)。onStartCommand()
方法去安排一个在另一个线程或异步执行的任务,那么你可能想要使用START_FLAG_REDELIVERY
以让系统重传一个Intent给你以使它不会在被处理时该Service被杀死导致其丢失。onStartCommand()
的返回值(需要深入研究) 注意onStartCommand()
必须返回一个整形值。这个整型值描述了当Service被杀死后,系统应该怎样继续该Service。这个返回值必须是下面各常量中的一个:
onStartCommand()
方法返回后杀死了该Service,则不会再重新创建该Service,除非有pending intents传递给它。对于避免你的Service在不必要的时候运行和你的应用能够简单重启未完成的工作的情况,这是一个安全的选项。onStartCommand()
方法返回后杀死了该Service,则会重新创建该Service并调用onStartCommand()
方法,但不会重传最后的Intent。系统会调用onStartCommand()
附带null的intent,除非有pending intent去启动该Service,在这种情况下,会传递这些intents。onStartCommand()
方法返回后杀死了该Service,则会重新创建该Service并调用onStartCommand()
方法附带最后传递到该Service的Intent。任何pending intents是被轮流地传递。public void onCreate ()
public void onDestroy ()
public int onStartCommand (Intent intent, int flags, int startId)
startService(Intent)
方法时,该方法都会被调用。 startService(Intent)
方法提供。如果该Service被杀死后重启,且之前返回了除START_STICKY_COMPATIBILITY
之外的任何状态,则重启后该Intent为null。 0
,START_FLAG_REDELIVERY
,START_FLAG_RETRY
。 stopSelfResult(int)
来终止特定Service。 public abstract IBinder onBind (Intent intent)
Context.bindService
方法传递过来,用来绑定到该Service的。 public boolean onUnbind (Intent intent)
public void onRebind (Intent intent)
public void onConfigurationChanged (Configuration newConfig)
public void onLowMemory ()
public void onTrimMemory (int level)
TRIM_MEMORY_COMPLETE
, TRIM_MEMORY_MODERATE
, TRIM_MEMORY_BACKGROUND
, TRIM_MEMORY_UI_HIDDEN
, TRIM_MEMORY_RUNNING_CRITICAL
, TRIM_MEMORY_RUNNING_LOW
, TRIM_MEMORY_RUNNING_MODERATE
。public void onTaskRemoved (Intent rootIntent)
ServiceInfo.FLAG_STOP_WITH_TASK
则你将不会接收到该回调。该Service将被简单的终止。 public final void startForeground (int id, Notification notification)
public final void stopForeground (boolean removeNotification)
public final void stopSelf ()
public final void stopSelf (int startId)
stopSelfResult(int)
的老版本public final boolean stopSelfResult (int startId)
IntentService是Service的子类,用来处理异步请求。Clients通过调用startService(Intent)
方法发送请求。该Service在需要时启动,用工作线程轮流处理每一个Intent,完成工作后终止自己。
“工作队列处理器”模式常用来从应用程序主线程卸载任务。IntentService类简化了这个模式。为了使用它,继承IntentService类并实现onHandleIntent(Intent)
方法。IntentService会接受Intents,创建工作线程,并在适当的时候终止该Service。
所有请求在一个单独的工作线程中处理,每次只能处理一个请求。
相对Service,IntentService做了如下处理:
onStartCommand()
的intents,以将处理工作从应用程序主线程中分离出去。onHandleIntent()
每次传递一个intent,所以你不需要担心多线程问题。stopSelf()
方法结束服务。onBind()
方法。onStartCommand()
方法,以发送intent到工作队列,然后到onHandleIntent()
方法。public int onStartCommand (Intent intent, int flags, int startId)
public void setIntentRedelivery (boolean enabled)
onStartCommand(Intent, int, int)
方法返回START_REDELIVER_INTENT
,这时如果进程在onHandleIntent(Intent)
方法返回前死掉,则进程会被重启并重新传递intent。如果有多个intent已经被传递,则只有最近传递的一个intent能够保证被重传。 onStartCommand(Intent, int, int)
方法返回START_NOT_STICKY
,这时如果进程死掉,则intent不会再被重传。protected abstract void onHandleIntent (Intent intent)
public class MyIntentService extends IntentService {
private static final String NAME = MyIntentService.class.getSimpleName();
private static final String TAG = "sxd";
public static final String INTENT_KEY = "intent_key";
public MyIntentService() {
super(NAME);
}
@Override
public void onCreate() {
Log.i(TAG, NAME + "--onCreate");
Log.i(TAG, NAME + "--onCreate++currentThread++id:" + Thread.currentThread().getId());
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, NAME + "--onStartCommand");
Log.i(TAG, NAME + "--onStartCommand++currentThread++id:" + Thread.currentThread().getId());
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG, NAME + "--onHandleIntent++begin:" + intent.getStringExtra(INTENT_KEY));
Log.i(TAG, NAME + "--onHandleIntent++currentThread++id:" + Thread.currentThread().getId());
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, NAME + "--onHandleIntent++end:" + intent.getStringExtra(INTENT_KEY));
}
@Override
public void onDestroy() {
Log.i(TAG, NAME + "--onDestroy");
Log.i(TAG, NAME + "--onDestroy++currentThread++id:" + Thread.currentThread().getId());
super.onDestroy();
}
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String NAME = MainActivity.class.getSimpleName();
private static final String TAG = "sxd";
private Button mStartService;
private Button mStopService;
private Button mBindService;
private Button mUnbindService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mStartService = (Button) this.findViewById(R.id.start_service);
mStartService.setOnClickListener(this);
mStopService = (Button) this.findViewById(R.id.stop_service);
mStopService.setOnClickListener(this);
mBindService = (Button) this.findViewById(R.id.bind_service);
mBindService.setOnClickListener(this);
mUnbindService = (Button) this.findViewById(R.id.unbind_service);
mUnbindService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_service:
startService();
break;
case R.id.stop_service:
stopService();
break;
/*case R.id.bind_service: bindService(); break; case R.id.unbind_service: unbindService(); break;*/
}
}
private void startService() {
Log.i(TAG, NAME + "--startService++mainThread++id:" + Thread.currentThread().getId());
Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra(MyIntentService.INTENT_KEY, "1");
startService(intent);
intent.putExtra(MyIntentService.INTENT_KEY, "2");
startService(intent);
intent.putExtra(MyIntentService.INTENT_KEY, "3");
startService(intent);
}
private void stopService() {
Intent intent = new Intent(this, MyIntentService.class);
stopService(intent);
}
/*private void bindService() { Intent intent = new Intent(this, MyService.class); bindService(intent, mConnection, BIND_AUTO_CREATE); } private void unbindService() { unbindService(mConnection); }*/
}
该示例程序,点击“启动服务”按钮,执行结果如下图
执行结果证明:
onHandleIntent(Intent)
方法确实是在独立线程运行。该示例程序,点击“启动服务”按钮后,在所有请求未处理完成时,点击“停止服务”按钮,执行结果如下图
观察执行结果可知,当主动停止Service后,Service立即终止,但当前正在处理的任务不会立即终止,而是执行完成后终止,由于Service终止,则后续任务不会再被进行传递处理。
public class ImitateIntentService extends Service {
private static final String NAME = ImitateIntentService.class.getSimpleName();
private static final String TAG = "sxd";
public static final String INTENT_KEY = "intent_key";
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
Log.i(TAG, NAME + "--ServiceHandler++begin:" + bundle.getString(INTENT_KEY));
Log.i(TAG, NAME + "--ServiceHandler++currentThread++id:" + Thread.currentThread().getId());
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
Log.i(TAG, NAME + "--ServiceHandler++end:" + bundle.getString(INTENT_KEY));
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
Log.i(TAG, NAME + "--onCreate");
Log.i(TAG, NAME + "--onCreate++currentThread++id:" + Thread.currentThread().getId());
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread(NAME, Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, NAME + "--onStartCommand");
Log.i(TAG, NAME + "--onStartCommand++currentThread++id:" + Thread.currentThread().getId());
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
Bundle bundle = new Bundle();
bundle.putString(INTENT_KEY, intent.getStringExtra(INTENT_KEY));
msg.setData(bundle);
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, NAME + "--onBind");
Log.i(TAG, NAME + "--onBind++currentThread++id:" + Thread.currentThread().getId());
// We don't provide binding, so return null
return null;
}
@Override
public void onDestroy() {
Log.i(TAG, NAME + "--onDestroy");
Log.i(TAG, NAME + "--onDestroy++currentThread++id:" + Thread.currentThread().getId());
}
}
该示例程序使用Service和Handler,实现了IntentService功能。
该示例程序,点击“启动服务”按钮,执行结果如下图
执行结果和IntentService示例完全一样。
public class MyService extends Service {
private static final String NAME = MyService.class.getSimpleName();
private static final String TAG = "sxd";
private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {
//该Service被首次创建时调用
Log.i(TAG, NAME + "--onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, NAME + "--onStartCommand");
//该Service正在运行,client再次调用startService()时调用
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, NAME + "--onBind");
//client调用bindService()绑定到该Service时调用
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, NAME + "--onUnbind");
//所有已绑定到该Service的client调用unbindService()与该Service解绑时调用
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
Log.i(TAG, NAME + "--onRebind");
//当onUnbind()被调用后,又有新的client调用bindService()来绑定该Service时调用
super.onRebind(intent);
}
@Override
public void onDestroy() {
Log.i(TAG, NAME + "--onDestroy");
//该Service不再使用,销毁时调用
super.onDestroy();
}
class MyBinder extends Binder {
public void doSomething() {
Log.i(TAG, NAME + "--MyBinder++doSomething()");
}
}
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String NAME = MainActivity.class.getSimpleName();
private static final String TAG = "sxd";
private Button mStartService;
private Button mStopService;
private Button mBindService;
private Button mUnbindService;
private MyService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mStartService = (Button) this.findViewById(R.id.start_service);
mStartService.setOnClickListener(this);
mStopService = (Button) this.findViewById(R.id.stop_service);
mStopService.setOnClickListener(this);
mBindService = (Button) this.findViewById(R.id.bind_service);
mBindService.setOnClickListener(this);
mUnbindService = (Button) this.findViewById(R.id.unbind_service);
mUnbindService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_service:
startService();
break;
case R.id.stop_service:
stopService();
break;
case R.id.bind_service:
bindService();
break;
case R.id.unbind_service:
unbindService();
break;
}
}
private void startService() {
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
private void stopService() {
Intent intent = new Intent(this, MyService.class);
stopService(intent);
}
private void bindService() {
Intent intent = new Intent(this, MyService.class);
bindService(intent, mConnection, BIND_AUTO_CREATE);
}
private void unbindService() {
unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, NAME + "--onServiceDisconnected++name:" + name.getClassName());
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, NAME + "--onServiceConnected++name:" + name.getClassName());
myBinder = (MyService.MyBinder) service;
myBinder.doSomething();
}
};
}
IMyServiceAIDL.aidl文件
interface IMyServiceAIDL {
int add(int a, int b);
}
远程Service运行在独立进程中,Activity等组件要与其通信,则需要使用AIDL来实现跨进程通信。AIDL是Android接口定义语言。创建.aidl文件,定义需要进行的操作。.aidl文件编译后,会自动生成相应的.java文件。
MyService.java文件
public class MyService extends Service {
private static final String NAME = MyService.class.getSimpleName();
private static final String TAG = "sxd";
@Override
public void onCreate() {
//该Service被首次创建时调用
Log.i(TAG, NAME + "--onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, NAME + "--onStartCommand");
//该Service正在运行,client再次调用startService()时调用
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, NAME + "--onBind");
//client调用bindService()绑定到该Service时调用
return new MyServiceAIDLImpl();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, NAME + "--onUnbind");
//所有已绑定到该Service的client调用unbindService()与该Service解绑时调用
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
Log.i(TAG, NAME + "--onRebind");
//当onUnbind()被调用后,又有新的client调用bindService()来绑定该Service时调用
super.onRebind(intent);
}
@Override
public void onDestroy() {
Log.i(TAG, NAME + "--onDestroy");
//该Service不再使用,销毁时调用
super.onDestroy();
}
class MyServiceAIDLImpl extends IMyServiceAIDL.Stub {
@Override
public int add(int a, int b) throws RemoteException {
return a + b;
}
}
}
onBind()方法中需要返回.aidl文件定义接口的实例。
在manifest中注册Service
<service android:name=".MyService" android:process=":remote">
<intent-filter>
<action android:name="com.example.sunxiaodong.remoteservice.MyService"/>
</intent-filter>
</service>
Service注册时,使用android:process
声明属性将该Service定义为远程Service。因为在其它应用程序中,不能获得该Service的具体类名,所以如果需要在其它应用程序中使用该远程Service,则需要为该Service定义action。
MainActivity.java文件
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String NAME = MainActivity.class.getSimpleName();
private static final String TAG = "sxd";
private Button mStartService;
private Button mStopService;
private Button mBindService;
private Button mUnbindService;
private EditText mAddendOne;
private EditText mAddendTwo;
private TextView mResult;
private IMyServiceAIDL mIMyServiceAIDL;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mStartService = (Button) this.findViewById(R.id.start_service);
mStartService.setOnClickListener(this);
mStopService = (Button) this.findViewById(R.id.stop_service);
mStopService.setOnClickListener(this);
mBindService = (Button) this.findViewById(R.id.bind_service);
mBindService.setOnClickListener(this);
mUnbindService = (Button) this.findViewById(R.id.unbind_service);
mUnbindService.setOnClickListener(this);
mAddendOne = (EditText) this.findViewById(R.id.addend_one);
mAddendTwo = (EditText) this.findViewById(R.id.addend_two);
mResult = (TextView) this.findViewById(R.id.result);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_service:
startService();
break;
case R.id.stop_service:
stopService();
break;
case R.id.bind_service:
bindService();
break;
case R.id.unbind_service:
unbindService();
break;
}
}
private void startService() {
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
private void stopService() {
Intent intent = new Intent(this, MyService.class);
stopService(intent);
}
private void bindService() {
Intent intent = new Intent(this, MyService.class);//显示启动Service
/*Intent intent = new Intent("com.example.sunxiaodong.remoteservice.MyService"); intent.setPackage("com.example.sunxiaodong.remoteservice");//Android5.0后Service不能采用隐式启动,所以必须加上包名*/
bindService(intent, mConnection, BIND_AUTO_CREATE);
}
private void unbindService() {
unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIMyServiceAIDL = IMyServiceAIDL.Stub.asInterface(service);
try {
int result = mIMyServiceAIDL.add(Integer.parseInt(mAddendOne.getText().toString()), Integer.parseInt(mAddendTwo.getText().toString()));
mResult.setText(String.valueOf(result));
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
}
使用IMyServiceAIDL.Stub.asInterface()方法将传入的IBinder对象传换成了IMyServiceAIDL对象,接下来就可以调用在IMyServiceAIDL.aidl文件中定义的所有接口了。
该示例程序,填入两个加数后,点击“绑定服务”按钮,就可在结果位置,显示两个加数之和。
在该应用程序中,要使用其它应用程序的远程Service,需要将该远程Service的.aidl文件连同包名路径一起拷贝到该应用程序中。
client应用程序的MainActivity.java文件
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String NAME = MainActivity.class.getSimpleName();
private static final String TAG = "sxd";
private Button mStartService;
private Button mStopService;
private Button mBindService;
private Button mUnbindService;
private EditText mAddendOne;
private EditText mAddendTwo;
private TextView mResult;
private IMyServiceAIDL mIMyServiceAIDL;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mStartService = (Button) this.findViewById(R.id.start_service);
mStartService.setOnClickListener(this);
mStopService = (Button) this.findViewById(R.id.stop_service);
mStopService.setOnClickListener(this);
mBindService = (Button) this.findViewById(R.id.bind_service);
mBindService.setOnClickListener(this);
mUnbindService = (Button) this.findViewById(R.id.unbind_service);
mUnbindService.setOnClickListener(this);
mAddendOne = (EditText) this.findViewById(R.id.addend_one);
mAddendTwo = (EditText) this.findViewById(R.id.addend_two);
mResult = (TextView) this.findViewById(R.id.result);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_service:
startService();
break;
case R.id.stop_service:
stopService();
break;
case R.id.bind_service:
bindService();
break;
case R.id.unbind_service:
unbindService();
break;
}
}
private void startService() {
Intent intent = new Intent("com.example.sunxiaodong.remoteservice.MyService");
intent.setPackage("com.example.sunxiaodong.remoteservice");//Android5.0后Service不能采用隐式启动,所以必须加上包名
startService(intent);
}
private void stopService() {
Intent intent = new Intent("com.example.sunxiaodong.remoteservice.MyService");
intent.setPackage("com.example.sunxiaodong.remoteservice");//Android5.0后Service不能采用隐式启动,所以必须加上包名
stopService(intent);
}
private void bindService() {
Intent intent = new Intent("com.example.sunxiaodong.remoteservice.MyService");
intent.setPackage("com.example.sunxiaodong.remoteservice");//Android5.0后Service不能采用隐式启动,所以必须加上包名
bindService(intent, mConnection, BIND_AUTO_CREATE);
}
private void unbindService() {
unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIMyServiceAIDL = IMyServiceAIDL.Stub.asInterface(service);
try {
int result = mIMyServiceAIDL.add(Integer.parseInt(mAddendOne.getText().toString()), Integer.parseInt(mAddendTwo.getText().toString()));
mResult.setText(String.valueOf(result));
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
}
对远程Service的使用,基本上同相同应用程序内对远程Service的使用方法相同,只是在启动该Service时,需要使用action。
源码地址