服务的用法

SerVice

  • Service就是默默运行在后台的组件,可以理解为是没有前台的activity,适合用来运行不需要前台界面的代码
  • 服务可以被手动关闭,不会重启,但是如果被自动关闭,内存充足就会重启
开启方式
  • startService
    • 该方法启动的服务所在的进程属于服务进程
    • Activity一旦启动服务,服务就跟Activity一毛钱关系也没有了
  • bindService
    • 该方法启动的服务所在进程不属于服务进程
    • Activity与服务建立连接,Activity一旦死亡,服务也会死亡

服务的分类

  • 本地服务:指的是服务和启动服务的activity在同一个进程中
  • 远程服务:指的是服务和启动服务的activity不在同一个进程中

服务的生命周期

onCreate–>onStartCommand–>onDestory,与activity的不同,没有
onRestart和onResume,这一点注意。

启动方式示例

建立一个服务时,和广播一样,这里要继承自Service类
有两种方式启动和关闭

//这里是第一种方式
startService(intent);
stopService(intent);

第二种方式中,绑定服务需要传递三个参数,第一个就是要调用服务的意图对象,
第二个是一个ServiceConnection对象,这里需要实现该类,里面有有两个重写
的方法;最后一个表示标志位,一般用BIND_AUTO_CREATE

bindService(intent, conn, BIND_AUTO_CREATE);//绑定服务
//解绑服务
unbindService(conn);

class MyServiceConn implements ServiceConnection{
    //服务连接成功时,此方法调用
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // TODO Auto-generated method stub
    }

    //服务失去连接时,此方法调用
    @Override
    public void onServiceDisconnected(ComponentName name) {
        // TODO Auto-generated method stu   
    }
}
简单示例

需求:如果服务类中有一个方法,怎么去调用
绑定服务时,会触发服务的onBind方法,此方法会返回一个Ibinder的对象给
MainActivity,通过这个对象访问服务中的方法

服务类中的方法

@Override
public IBinder onBind(Intent intent) {
    // 返回一个Binder对象,这个对象就是中间人对象
    return new Tim();
}
class Tim extends Binder implements PublicBusiness{
    public void run(){
        banZheng();
    }
}
public void banZheng(){
    System.out.println("帮你来办证");
}

PublicBusiness接口中只定义一个未实现的run方法就行

public interface PublicBusiness {

    void run();
}

主activity中的调用步骤

private Intent intent;
private MyServiceConn conn;
PublicBusiness pb;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    intent = new Intent(this, LeaderService.class);
    conn = new MyServiceConn();
    //绑定服务
    bindService(intent, conn, BIND_AUTO_CREATE);
}
public void click(View v){
    //调用服务的办证方法
    pb.run();
}
class MyServiceConn implements ServiceConnection{

    //连接服务成功,此方法调用
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // TODO Auto-generated method stub
        pb = (PublicBusiness) service;
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
        // TODO Auto-generated method stub  
    }
}

该示例有点类似于找领导办事一样,需要通过一个中间人与领导进行交流,而小
员工与中间人交流,而中间人就是定义的Tim类。

使用服务注册广播接收者

这里的广播用的不是在清单文件中操作的方式,而是使用代码注册

public class ScreenReceiver extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    String action = intent.getAction();
    if(Intent.ACTION_SCREEN_OFF.equals(action)){
        System.out.println("屏幕关闭");
    }
    else if(Intent.ACTION_SCREEN_ON.equals(action)){
        System.out.println("屏幕打开");
    }
 }
}

当点击按钮时,开启服务,并且触发服务中的广播接收者代码

//主activity中
public void start(View v){
    startService(intent);
}
public void stop(View v){
    stopService(intent);
}
//服务中
@Override
public void onCreate() {
    super.onCreate();
    //1.创建广播接收者对象
    receiver = new ScreenReceiver();
    //2.创建intent-filter对象
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    filter.addAction(Intent.ACTION_SCREEN_ON);

    //3.注册广播接收者
    registerReceiver(receiver, filter);

}
@Override
public void onDestroy() {
    super.onDestroy();
    //解除注册,解除注册之后,广播接收者将失去作用
    unregisterReceiver(receiver);
}
服务分为本地和远程之说,那么如何启动远程的服务内容呢

这里需要用到一个知识点:AIDL(安卓接口定义语言),是进程间通信接口,
作用就是用于进程间通信。应用场景:远程服务中的中间人对象,其他应
用是拿不到的,那么在通过绑定服务获取中间人对象时,就无法强制转换,
使用aidl,就可以在其他应用中拿到中间人类所实现的接口

示例步骤

1 创建两个项目,一个上面部署服务,另外一个在主activity上添加一个按钮,
当点击的时候,触发项目1上的服务。
2 过程和简单示例中的很相似,只不过相当于把主activity和服务分到两个项目
中实现,还有一点不同的是:这里的PayInterface.java接口类,后缀要改
为:PayInterface.aidl文件,并且服务中实现的部分也要改变:

public class PayService extends Service {
@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return new Mypay();
}
//这里是继承了Stub类
class Mypay extends Stub{
    public void  pay(){
        PayService.this.pay_money();
    }
}
public void pay_money(){
    System.out.println("调用pay方法");
    System.out.println("加密用户名,密码");
    System.out.println("建立连接");
}
}

主方法中调用

private Intent intent;
private MyServiceConn conn;
private PayInterface pin;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    intent=new Intent();
    conn=new MyServiceConn();
    intent.setAction("com.itma.pay");
    bindService(intent, conn, BIND_AUTO_CREATE);
}
class MyServiceConn implements ServiceConnection{

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // TODO Auto-generated method stub
        pin=Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        // TODO Auto-generated method stub

    }

}
public void click(View v){
    try {
        pin.pay();
    } catch (RemoteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

进程间通信的步骤
1. 把远程服务的方法抽取成一个单独的接口java文件
2. 把接口java文件的后缀名改成aidl
3. 在自动生成的PayInterface .java文件中,有一个静态抽象类Stub,它已经继承了binder类,实现了PayInterface接口,这个类就是新的中间人
4. 把aidl文件复制粘贴到另外一个项目,粘贴的时候注意,aidl文件所在的包名必须跟05项目中aidl所在的包名一致
5. 在另外一个项目中,强转中间人对象时,直接使用Stub.asInterface()

进程优先级
  1. 前台进程:拥有前台activity(onResume方法被调用),以下都能成为前台进程

    • 拥有一个正在与用户交互的activity(onResume调用)的进程
    • 拥有一个与正在和用户交互的activity绑定的服务的进程
    • 拥有一个正在“运行于前台”的服务——服务的startForeground方法调用
    • 拥有一个正在执行以下三个生命周期方法中任意一个的服务(onCreate(), onStart(), or onDestroy())
    • 拥有一个正在执行onReceive方法的广播接收者的进程
  2. 可见进程:拥有可见activity(onPause方法被调用)

    • 拥有一个不在前台,但是对用户依然可见的activity(onPause方法调用)的进程
    • 拥有一个与可见(或前台)activity绑定的服务的进程
  3. 服务进程:不到万不得已不会被回收,而且即便被回收,内存充足时也会被重启
  4. 后台进程:拥有后台activity(activity的onStop方法被调用了),很容易被回收
  5. 空进程:没有运行任何activity,很容易被回收
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值