理解Service
*windows中: 长期后台运行没有界面的进程就叫服务
*Android中: 运行在当前应用程序进程里面,长期后台运行,没有界面的组件.
*创建的时候也需要在清单文件里注册
PS:Service的父类是Activity的父类的父类,可以说Service是Activity的叔!!!
**
应用场景
**
一个特殊的没有界面的,可长期执行的”Activity”
1.比如,监测一个硬件是否被插入
2.连接服务器刷新最新的数据
3.定时轮询(开启子线程轮询. 轮询条件用flag控制)
注意:
1.服务运行在主线程里面,不可以直接在服务里面编写耗时的逻辑.需要开启子线程进行操作.
2.开启服务. startService(intent);
3.停止服务. stopService(intent); 停止服务时用flag=false控制
Service的生命周期
这个图中将开启的Service 和绑定的Service 分开,但是我们需要记住,任何Service 都潜在地允许被绑定。所以,一个被开启的Service 仍然可能被绑定。实现这些方法,可以看到两层嵌套的Service 的生命周期。
进程的优先级
*Foreground process
前台进程:用户正在操作的进程
*Visible process
可视进程:用户已经不能操作这个应用程序了,但是界面用户任然可以看到
*Service process
服务进程: 应用程序有一个服务代码正在运行.
注: 即使进程被回收,只要当内存充足时,service会被系统自动复活.
*Background process
后台进程: 应用程序有界面,但是界面被用户最小化(按home)
*Empty process
空进程: 应用程序没有任何运行的Activity, service.
优先级: 从上到下,依次减小
前台>可视>服务>后台>空进程
如何开启Service
一, 直接开启(标准开启模式) A Started Service
*在Activity中调用startService()方法创建,必须调用stopSelf()方法或者其他组件调用stopService()方法来停止它.
*缺点:
在Activity里面直接调用Service里面的方法,是行不通的. 不可以与服务进行通信.
二,绑定开启(绑定模式) A Bound Service
原理: 直接调用不行,找一个Service的内部类去间接调用服务内部的方法.
**调用bindService()来创建的,可以通过一个IBinder接口和service 进行通信.通过unbindService()方法来关闭这种连接.
**一个service 可以同时和多个Activity绑定,当多个客户都解除绑定之后,系统会销毁service.
三,混合的方式开启服务
严格按照步骤编写代码
1.start的方式开启服务(保证服务长期在后台运行)
2.bind 绑定服务(调用服务的方法)
3.unbind的方式解除绑定服务
4.stop 停止服务
说了这么多,该来真东西了,直接上案例~~
<案例一: 绑定开启Service,找有关部门办暂住证>
需求:
模拟某人(Activity)需要办一个暂住证,直接找有关部门(Service)很难办成,但是通过一个中介(Service内部类)给点手续费,就水到渠成的办成了!!
步骤:
1.创建一个CertificateService类继承Service,重写onBind()方法, 配置清单文件.
public class CertificateService extends Service {
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
//返回一个中间人(中介)
return new MyBinder();
}
//Service内部的方法,Activity不能直接访问
public void methodInService(String name){
System.out.println("我是服务里的方法,我被调用了");
Toast.makeText(CertificateService.this, name+"您好!您的暂住证已经办好...", 0).show();
}
/**
*内部类. 即中间人.
*IService是事先创建好的一个Interface, 只有一个方法callMethodInService().
*/
private class MyBinder extends Binder implements IService{
@Override
public void callMethodInService(String name, int money) {
if (money>200) {
methodInService(name);
}else {
Toast.makeText(CertificateService.this, "对不起,我们这里得按制度办事...", 0).show();
}
}
}
}
2.在MainActivity里通过中间人MyBinder调用Service里的方法MethodInService().
public class MainActivity extends Activity {
private IService iService;
private MyConn conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 绑定服务代理
* @param view
*/
public void bind(View view){
Intent intent = new Intent(MainActivity.this,CertificateService.class);
conn=new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);
}
/**
* 通过代理调用服务里的方法
* @param view
*/
public void call(View view){
iService.callMethodInService("歪歪", 300);
}
/**
* 解除绑定
* @author Administrator
*
*/
public void unBind(View view){
unbindService(conn);
}
/**
* 内部类,用于连接Activity和中间人
* @author Administrator
*
*/
public class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iService=(IService)service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
3.Activity的布局如下:
线性布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:onClick="bind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定中介"
/>
<Button
android:onClick="call"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始办证"
/
</LinearLayout>
<案例二: AIDL远程服务: 一个程序调用另一个程序的功能>
1.创建一个Service所在的项目,键一个IService接口,写好callMethodInService()方法后将其改成IService.aidl格式文件.
具体代码:
package com.heima.wechat;
interface IService {
void callMethodInService();
}
2.根据以上目录结构写好weChatService.
代码:
public class weChatService extends Service {
//内部类,重写IService里的方法
private class MyBinder extends IService.Stub {
@Override
public void callMethodInService() throws RemoteException {
methodInService();
}
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
@Override
public void onCreate() {
System.out.println("微信被开启了...");
super.onCreate();
}
public void methodInService() {
System.out.println("我是微信的摇一摇方法,我被调用了");
}
@Override
public void onDestroy() {
System.out.println("微信被关闭了...");
super.onDestroy();
}
}
3.把远程服务IService.aidl文件拷贝到本地应用程序(远程访问)的工程目录里面,包名保持一致.
4.按以上目录,编写MainActivity的代码
如下:
public class MainActivity extends Activity {
private IService iservice;
private MyConn conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conn=new MyConn();
}
public class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("哈哈,绑定到了微信..");
//获取中间人对象
iservice=IService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
//绑定到Service
public void bind(View v){
Intent intent=new Intent();
intent.setAction("com.heima.wechat");
bindService(intent, conn, BIND_AUTO_CREATE);
}
//通过中间人调用Service里的方法
public void call(View v){
try {
iservice.callMethodInService();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
5.远程访问的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:onClick="bind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定远程服务" />
<Button
android:onClick="call"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="分享到微信" />
</LinearLayout>
AIDL运行结果如下:
系统服务
所有的系统服务都是同一个API, getSystemServices() 适用于Application Framework层所有的XXXManager
完了~~
Android四大组件已更新完, 希望可以和朋友们共同探讨,共同进步~~~Peace!