服务
服务的生命周期
---
1 开启服务的生命周期
完整的生命周期:onCreate()-->onStartCommand()-->onDestroy()
* 开启服务:onCreate()-->onStartCommand()
* 停止服务:onDestroy()
* 特点:
1. 服务可以被多次开启,每次开启都执行onStartCommand()方法
2. 服务只能被停止一次,多次停止服务
3. 长期运行在后台
2 bind绑定服务的生命周期
完整的生命周期:onCreate()-->onBind()-->onUnbind()-->onDestroy()
* 绑定服务:onCreate()-->onBind()
* 解绑服务:onUnbind()-->onDestroy()
* 特点:
1. 服务只能被绑定一次,多次绑定无效
2. 服务只能被解绑一次,多次解绑会抛出异常
3. 不可以长期运行在后台
4. Activity和绑定他的服务同生共死
5. 可以调用服务里的方法
* 区别: 1. 能不能长期运行在后台
2. 能不能调用服务里的方法
绑定服务调用方法
---
3 绑定服务调用服务里的方法
服务被绑定成功后,拿到服务返回的中间人,用中间人间接调用服务里的方法
Activity:
1 /** 2 * bind方式绑定服务 3 */ 4 public void bind(View v) { 5 /** 6 * service :意图 ServiceConnection:Activity和service连接通道 7 * BIND_AUTO_CREATE:绑定服务时,如果服务不存在,则创建 8 */ 9 Log.d(TAG, "bind:1. 绑定服务"); 10 conn = new MyConn(); 11 bindService(intent, conn, BIND_AUTO_CREATE); 12 } 13 14 /** 15 * 解绑服务 16 */ 17 public void unbind(View v) { 18 19 Log.d(TAG, "unbind:服务被解绑啦。。。"); 20 unbindService(conn); 21 } 22 23 /** 24 * 调用服务里的方法 25 * 26 */ 27 public void diao(View v) { 28 29 xiaowu.qianShouMM(99999); 30 Log.d(TAG, "diao:6. 用服务的内部类间接调用服务里的方法"); 31 } 32 33 class MyConn implements ServiceConnection { 34 35 // Activity和service已经连接成功喽 36 @Override 37 public void onServiceConnected(ComponentName name, IBinder service) { 38 39 Log.d(TAG, "onServiceConnected:4. 服务连接成功了"); 40 xiaowu = (WuMiShu) service; 41 Log.d(TAG, "onServiceConnected:5. 在Activity中拿到了服务里的内部类"); 42 } 43 44 // 失去连接了 45 @Override 46 public void onServiceDisconnected(ComponentName name) { 47 48 Log.d(TAG, "onServiceDisconnected: 失去连接了..."); 49 } 50 } 51 52 @Override 53 protected void onDestroy() { 54 55 unbindService(conn); 56 super.onDestroy(); 57 }
Service:
1 /** 2 * 服务里的方法 3 */ 4 public void methodInService() { 5 6 Toast.makeText(this, "我是服务里的方法,来吊我啊。。。", 0).show(); 7 } 8 9 @Override 10 public IBinder onBind(Intent intent) { 11 12 Log.d(TAG, "onBind:2. 服务被绑定成功喽"); 13 Log.d(TAG, "onBind 3. 服务绑定成功后,返回WuMiShu"); 14 return new WuMiShu(); 15 } 16 17 /** 18 * 服务里的内部类, 内部类调用外部类的方法 中间人 小蜜 19 */ 20 public class WuMiShu extends Binder { 21 22 /** 23 * 调用外部类的方法 24 * 25 * @param money 26 */ 27 public void qianShouMM(int money) { 28 29 if (money > 5000) { 30 methodInService(); 31 } else { 32 Toast.makeText(MyService.this, "屌丝注定单身", 0) 33 .show(); 34 } 35 } 36 } 37 38 @Override 39 public boolean onUnbind(Intent intent) { 40 41 Log.d(TAG, "onUnbind:"); 42 return super.onUnbind(intent); 43 } 44 45 @Override 46 public void onCreate() { 47 48 super.onCreate(); 49 Log.d(TAG, "onCreate:"); 50 } 51 52 @Override 53 public int onStartCommand(Intent intent, int flags, int startId) { 54 55 Log.d(TAG, "onStartCommand:"); 56 return super.onStartCommand(intent, flags, startId); 57 } 58 59 @Override 60 public void onDestroy() { 61 62 super.onDestroy(); 63 Log.d(TAG, "onDestroy:"); 64 }
4 绑定服务抽取接口
隐藏具体的实现细节,只暴露程序员想暴露的方法
1. 写一个接口,接口里写一个方法
2. 让服务的内部类ChenMiShu实现IService接口
3. 当Activity这边连接成功后,Binder强转成IService接口类型
4. 用IService接口间接调用服务里的方法
5 混合方式开启服务
为什么要用混合方式启动服务:即想服务长期运行在后台,又想调用服务里的方法
开发中推荐的步骤:startService()保证服务长期运行在后台
bindService()可以调用服务里的方法
unBindService()解除绑定服务
stopService()后台就没有这个服务了
远程服务
---
6 本地服务和远程服务
* 本地服务:服务组件在自己的应用程序里
* 远程服务:服务组件不在自己的应用程序里
7 本地应用调用远程服务中的方法
AIDL:android interface defination language 安卓接口定义语言
编写步骤:
远程服务工程:
1. 把IService.java改成.aidl文件
2. 去掉public 修饰符
3. 让服务里的内部类继承IService.Stub
Service:
1 @Override 2 public IBinder onBind(Intent intent) { 3 Log.d(TAG, "onBind"); 4 return new ChenMiShu(); 5 } 6 /** 7 * 陈秘书 8 */ 9 class ChenMiShu extends IService.Stub{ 10 11 @Override 12 public void callMethodInRemoteService() { 13 qianShouYangNiu(); 14 } 15 16 } 17 18 /** 19 * 远程服务里的方法 20 */ 21 public void qianShouYangNiu(){ 22 Log.e(TAG, "qianShouYangNiu:我来了,你在哪?我在美国,咱们中间隔着一个太平洋...."); 23 }
IService.aidl
1 interface IService { 2 3 /** 4 * 调用远程服务里 的方法 5 */ 6 void callMethodInRemoteService(); 7 }
本地应用:
4. 创建一个和远程服务.aidl文件所在的一样包
5. 吧06工程里的IService.aidl文件复制到这个包里
6. 用IService.Stub.asInterface(service)强转成IService
7. 间接调用远程服务了的方法,处理RemoteException
Activity:
1 /** 2 * start开启服务 3 * 4 * @param v 5 */ 6 public void start(View v) { 7 intent = new Intent(); 8 // 设置动作 9 intent.setAction("wo.kan.dai.ma.ru.chu.lian"); 10 // 可选,设置数据 11 // 默认是DEFAULT,可以不写 12 startService(intent); 13 } 14 15 /** 16 * stop停止服务 17 * 18 * @param v 19 */ 20 public void stop(View v) { 21 stopService(intent); 22 } 23 24 /** 25 * bind绑定服务 26 * 27 * @param v 28 */ 29 public void bind(View v) { 30 Intent service = new Intent(); 31 // 设置动作 32 service.setAction("wo.kan.dai.ma.ru.chu.lian"); 33 34 mConn = new MyConn(); 35 bindService(service, mConn, BIND_AUTO_CREATE); 36 } 37 38 /** 39 * Activity和远程服务里的连接通道 40 */ 41 class MyConn implements ServiceConnection { 42 @Override 43 public void onServiceConnected(ComponentName name, IBinder service) { 44 Log.d(TAG, "onServiceConnected:连接成功"); 45 // service强转成 IService接口类型 46 mService = IService.Stub.asInterface(service); 47 } 48 49 @Override 50 public void onServiceDisconnected(ComponentName name) { 51 } 52 53 } 54 55 /** 56 * 解绑服务 57 * 58 * @param v 59 */ 60 public void unbind(View v) { 61 unbindService(mConn); 62 } 63 64 /** 65 * 调用远程服务里的方法 66 */ 67 public void callremotemethod(View view) { 68 try { 69 mService.callMethodInRemoteService(); 70 } catch (RemoteException e) { 71 e.printStackTrace(); 72 } 73 }
IService.aidl
1 interface IService {
2
3 /**
4 * 调用远程服务里 的方法
5 */
6 void callMethodInRemoteService();
7 }
清单代码:
1 <activity 2 android:name="cn.zxr.local.MainActivity" 3 android:label="@string/app_name" > 4 <intent-filter> 5 <action android:name="android.intent.action.MAIN" /> 6 7 <category android:name="android.intent.category.LAUNCHER" /> 8 </intent-filter> 9 </activity>