service

来源:互联网 发布:js 布尔值取反 编辑:程序博客网 时间:2024/06/16 01:52

service是一个不能被看见的activity,因此service是不能够和用户进行直接交互;简而言之:服务就是运行在后台的一个activate;

  • 服务的声明:
    在manifest中使用来进行声明并进行配置相关属性;

  • 服务的启动:
    服务的启动方式分为两种:1.startservice 2.bindservice
    对应服务的结束方式:1.stopservice 2.unbindservice
    对于服务而言 同样拥有自己的声明周期:
    startservice-oncreate-onstart-运行
    stopservice-ondestroy-停止
    特别说明:如果service 服务没有开始的时候那么是和上面的声明周期一样运行 如果服务已经运行 我们再次开启服务 那么服务是不会被创建第二次的 也就是服务运行后重复开启同一个服务只会在第一次开启的时候调用oncreate方法
    同样的 如果说服务停止后那么系统回调摧毁服务方法(ondestroy)如果说用户直接退出程序而没有关闭服务,那么服务会一直在后台运行;
    简单举例说明:qq音乐,当用户直接使用home键或者返回键等后台音乐会一直处于播放状态,当用户按下停止键时(停止键监听中有stopservice方法)才会关闭服务;

  • 通过绑定服务的方式开启服务:
    生命周期如下:
    bingsercice-oncreate-onbind-运行
    onunbindservice-ondestroy-结束
    说明:
    使用服务绑定:
    在service中onbind是一个提供给acticity 用户数据交互的接口,通过该接口我们能够实现服务和acticity的交互;
    服务通常是在后台运行的,但是由于服务的优先级比较低,一旦出现内存紧张不够等情况,就有可能被系统回收掉这部分内存,如果我们不希望被回收掉,服务也不会出现中断的情况,这就得了解前台服务

  • 前台服务:
    前台服务和后台的区别在于我们能够在手机上看到程序图标的运行显示在状态栏中,这就是前台服务一直在运行的标志;
    如何将一个普通的服务转化为前台服务 只需要在server中的oncreat方法中添加以下代码就能实现;
    ` Notification notification=new Notification(R.drawable.ic_launcher, “你有新的消息啦”, System.currentTimeMillis());

        Intent in=new Intent(this,MainActivity.class);    PendingIntent pendingintent=PendingIntent.getActivity(this, 0, in, 0);    notification.setLatestEventInfo(this, "你好", "欢迎光临", pendingintent);    startForeground(1, notification);`    再次启动服务的时候就会在状态栏找到该通知信息;
  • 远程服务的使用(上)
    为什么要使用远程服务?
    远程服务会将服务放置在不同的进程中;注意这里是进程,而不是线程,附带一说的就是服务是处在主线程的,如果不信,可以使用Thread.currentThread.getId()(令外区分不同进程的方法 process.myPid()来查看进程);分别放置在acitivity中和service中进行查看;
    继续原来的话题,当放在不同的进程中,当然就不存在主线程的一些问题比如说阻塞主线程,耗时操作等影响了;
    如何转化为远程服务?
    只需要打开manifest 在你生命service中添加process 属性其值为“:remote”
    使用远程服务注意:
    一旦将服务变成不同进程的时候,那么我们再去使用bindservice的时候肯定会崩溃,因为在当前进程中是查找不到的;如果关联不同进程间的服务,则需要使用AIDL来进行通讯了;
    什么是aidl?
    aidl(Android Interface Definition Language)是Android接口定义语言的意思,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。
    aidl创建方式?
    在eclipse中创建aidl文件,建议大家先写个java文件定义好接口 该接口是实现acticity和不同进程的service通讯使用的,然后再创建一个file文件后缀为aidl,将java中的所有包括ctrl+c/v过去,然后删除java就可以了 。如果你发现gen文件下生成了一个对应的一个java文件表明创建成功 否则需要检查你的代码是否正确了。

    创建接口对象 接口名.stub=new stub(),会自动重写aidl文件中的方法;
    在onbind中返回接口对象,该对象;
    在acticity中去实现该接口,只需要在serverconnected中把IBinder对象作为接口赋值给我们的接口对象就可以;这样就利用了aidl实现跨进程的通讯;
    具体操作代码如下:

    server中:

@Override    public IBinder onBind(Intent arg0) {        Log.e("service", "onBind");        return mbinder ;    }    myaidl.Stub mbinder=new Stub() {        //重写的方法    }

acticity中:

private myaidl myaidls;private ServiceConnection  con=new ServiceConnection() {    @Override    public void onServiceDisconnected(ComponentName arg0) {        myaidls=null;    }    @Override    public void onServiceConnected(ComponentName arg0, IBinder arg1) {        myaidls=myaidl.Stub.asInterface(arg1);//通过myaidls调用接口中的方法 传值    }};
  • 远程服务(下)
    通常我们使用远程服务希望的是在不同程序间进行交互;而不是如上面一样在一个程序中进行操作;
    如何在不同程序间进行操作?
    不同的程序运行在不同的进程中 同样是使用aidl来进行交互,
    创建一个不同的app项目(取名client),
    将上面项目中的你放接口的包完整的复制在client中,
    同样的在acticity中去使用aidl接口 和上面acticity中代码一样,这里我就不再复制一次到这里,还是不知道怎么做的看上面代码 复制 粘贴。

    说明:
    在不同的项目中使用同一个服务的时候,bindserver所绑定的intent只能使用隐式方式。因为client中是没有服务的 。
    所以只需要在server中添加进入动作 intent-fileter 并声明action
    代码如下:<service android:name="com.example.service.myservice"
    android:process=":remote">
    <intent-filter >
    <action android:name="com.example.service.myaidl"/>
    </intent-filter>
    </service>