Android service 服务 笔记

本文详细介绍了Android中的Service组件,包括其特点、启动与停止方式、进程内及跨进程使用方法,并深入探讨了AIDL在实现远程服务中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自http://enefry.iteye.com/blog/851581

android 中的 Service 是一个优先级比较高的 系统组件 ,他不是一个独立的进程也不是一个线程 !  

文档中有说明: 

A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of. 
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors). 
Service 没有用户界面,可以认为是在系统中永久运行的组件 .(这个是一个非常重要的特性 ) 

( 如果不是调用 stopService,unbindService,或者 stopSelf() 系统会让他一直运行下去,就算因为没有资源暂时停止,稍后也会再次运行,就算手动停止所在进程,系统也会重新启动该服务.) 

启动: 

可以使用 Context.startService(Intent) 或者 Context.bindService(Intent intent, ServiceConnection connn, int flags); 启动. 

停止: 

使用Context.stopService(Intent) 或者 Context.unBindService(ServiceConnection); 停止 . 但是必须所有服务连接关闭之后Service才能真正停止 ! 

使用准备: 需要在 AndroidManifest.xml中注册你的 Service 

比如: ( 简单点的) <service android:name =".LocalService"/> 


再如: ( 复杂点的): 

    <service android:name =".MyService"    ------名字这是必须的 

                android:process =":service"                ------进程名 
    > 
        <intent-filter>                                              
        <!-- AIDL完整路径名。必须指明,客户端能够通过AIDL类名查找到它的实现类 --> 
            <action android:name="com.en.demo.service.remoteServices.MyServiceBinder" /> 
        </intent-filter>    
    </service> 

进程内使用: 

可以通过startService(Intent);来启动 service 这个方法可以使用在一些自动执行的服务中,比如自动检测手机信息,自动检测软件版本等. 

通过 boolean android.content.ContextWrapper.bindService(Intent service, ServiceConnection conn, int flags) 可以绑定服务( 绑定是什么东东? 我的理解就只是给你一个对象 ,让你可以找到 你的服务的对象 ,这样可以调用服务的功能 ) 绑定之后就可以 调用啦. 

其中参数 : Intent 就是和startService一样都是需要告诉系统启动那个服务 

   ServiceConnection 就是一个连接成功调用的接口 当服务启动成功,系统将调用这个接口的 onServiceConnected    (ComponentName name, IBinder service)方法 这个方法传入了可以 找到服务的 参数 

  flags 是标记那个调用者的 

为什么说 这样可以找到服务呢? 

如果我们继承了Service 可以看到 Service中有一个 未实现的方法: public IBinder onBind(Intent intent) ; 

可以看到这里返回的是一个 IBinder 和前面 onServiceConnected传入的参数一样.一切就是从这里开始做文章的. 

这是我的例子中的一个服务: 

public class LocalService extends Service { 

   
    class MyBinder extends Binder{      // Binder 是 IBinder 接口的一个实现可以让我们不必写出全部抽象方法 
        public Service getService(){ 
            return LocalService.this;            
        } 
    } 
    
    @Override 
    public IBinder onBind(Intent intent) {        
        return new MyBinder(); 
    } 
    
  /**** 这个服务的 一些功能  ( 略 )***/      } 

从这里开始我们可以看到 MyBinder 可以返回我们的 Service 对象. 

从调用那里就可以这样做 

// 创建本地调用对象 
private ServiceConnection localConnection = new ServiceConnection() { 

    @Override 
    public void onServiceConnected(ComponentName name, IBinder service) { 
        /* 获得对象 */ 
        localService = (LocalService) ((LocalService.MyBinder) service) 
                .getService();   // 这里我们就可以获得 这个服务的引用了. 
        System.out.println("Bind local Service Success: " + localService); 

    } 
    @Override 
    public void onServiceDisconnected(ComponentName name) { 
        localService = null; 
    } 
}; 


但是这样引用了有什么用 ? 我的例子中运行界面是 : 

这里点击  " 获取名字 "按钮时候的代码是: 

public void onClick(View v) { 
                try { 
                    if (onBind) { 
                        showResult.setText("本地服务->获取名字: " 
                                + localService.getName());  // getName 是一个功能 
                    } else { 
                        Toast.makeText(StartActivity.this, "请先绑定服务 ", 
                                Toast.LENGTH_SHORT).show(); 
                    } 

                } catch (RemoteException e) { 
                    e.printStackTrace(); 
                } 



我们就可以直接使用 服务的实例进行工作了. 

具体功能可以看工程里面的代码. 







跨进程服务: 

我们可以调用系统提供的服务,比如 

ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));            // 这里 获得一个 系统服务am.restartPackage(getPackageName()); 

这样可以关闭当前进程 


我们的服务也可以为别人的程序服务,只要我们实现了接口,并在androidMainfast.xml中写清楚了就可以了 

更重要的我们需要了解一个 AIDL ( android interface definition language )接口描述语言 

我们不可能无缘无故自己的程序中写一个 interface 然后就说那是某个服务的接口吧.我们怎么样才知道有这个接口呢? aidl 提供了这个功能. 

提供服务端: 

当我们创建一个 aidl 文件 并在其中写入我们的接口的时候,adt 会自动生成对应的接口文件 .java 文件这样我们在我们的服务中实现这个接口就可以了. 


比如我这个例子中是在一个 RemoteServices的工程中 实现提供了一个服务, 

这个服务提供了那些对外服务? 我们就在 MyServiceBinder .aidl这个文件中描述了. 

aidl 这个文件使用的语法与 java一样 
package com.en.demo.service.remoteServices; 

//import com.en.demo.service.MyObject; 

interface MyServiceBinder{ 

    int getAdd(int a,int b); 
    String getName(); 
    void setName(String name); 
    //MyObject getObj(); 
    void makeBoardCast(); 


这样在MyService中再: 

    用一个MyBinder类来继承 
public class MyBinder extends MyServiceBinder.Stub{ //// z注意这里继承的是 Stub这个 类!!! 

    /* 服务提供的一些方法 */ 
    public int getAdd(int a, int b) throws RemoteException { 
        return a + b; 
    } 


    public String getName() throws RemoteException { 
        return MyService.this.name; 
    } 

    
    public void setName(String name) throws RemoteException { 
        MyService.this.name = name; 
    } 


    public IBinder asBinder() { 
        return MyBinder.this; 
    } 

    
    public void makeBoardCast() throws RemoteException { 
        boardCast(); 
    } 





而在接收端: 

MyServiceBinder remoteService ; 

// 创建远程调用对象 
    private ServiceConnection remoteConnection = new ServiceConnection() { 

        public void onServiceConnected(ComponentName name, IBinder service) { 
            // 从远程service中获得AIDL实例化对象 
            remoteService = MyServiceBinder.Stub.asInterface(service); 
            System.out.println("Bind remote Service Success:" + remoteService); 
        } 

        public void onServiceDisconnected(ComponentName name) { 
            remoteService = null; 
        } 
    }; 

这样我们就可以调用这个服务了.... 


想要更具体的实现,看代码.这个远程的服务有开启新线程进程操作,并通过广播通知调用者 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值