Android 四大组件 Service实现原理以及AIDL语言的使用详解

1、Service概念介绍以及生命周期解析

Service是Android系统提供的四大组件之一,它的地位与Activity是并列的,只不过没有Activity的使用频率高。顾名思义,Service就是运行在后台的一种服务程序,一般很少与用户交互,因此service没有可视化界面。

定义一个简单的service类比较简单,只需要继承Service类,实现其生命周期几个方法,然后在Manifest文件中添加service标签即可。

Service有自己的生命周期,我们可以使用startService()启动一个service或者使用bindService()来绑定一个存在的service,还可以通过RPC(远程进程调用)机制来实现不同进程中的service的调用。

Service的生命周期介绍 :

使用startService()启动 : onCreate() → onStart() ;

如果对已经启动的service继续调用startService的话,则只进行onStart() ;

使用stopService()关闭 : onDestroy() ;

使用bindService()启动绑定service时,只会调用onCreate() →onBind(),永远不会调用onStart() .

2、本地Service不和Activity进行交互情况

java code :

    public class ServiceA extends Service {  
      
        @Override  
        public void onCreate() {  
            super.onCreate();  
            Log.i("service", "onCreate...");  
        }  
          
        @Override  
        public void onStart(Intent intent, int startId) {  
            super.onStart(intent, startId);  
            //参数intent可以为activity向service传递相关信息   
            Log.i("service", "onStart..."+<span style="color:#CC33CC;">intent.getStringExtra("name")</span>);  
        }  
      
        @Override  
        public void onDestroy() {  
            super.onDestroy();  
            Log.i("service", "onDestroy...");  
        }  
      
          
            @Override  
        public IBinder onBind(Intent arg0) {  
            return null;//不需要和Activity进行交互时,可以直接返回null   
        }  
      
    }  
    public class MainActivity extends Activity {  
        private Button startBtn , stopBtn;  
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.service_demo);  
            startBtn = (Button) findViewById(R.id.startBtn);  
            stopBtn = (Button) findViewById(R.id.stopBtn);  
            startBtn.setOnClickListener(listener);  
            stopBtn.setOnClickListener(listener);  
        }  
          
        private OnClickListener listener = new OnClickListener() {  
            @Override  
            public void onClick(View view) {  
                Intent service = new Intent();  
                service.setAction("<span style="color:#FF0000;">serviceA</span>");  
                //向service传递值   
                service.putExtra("name", "i am service");  
                switch (view.getId()) {  
                case R.id.startBtn:  
                    startService(service);  
                    break;  
                case R.id.stopBtn:  
                    stopService(service);  
                    break;  
                default:  
                    break;  
                }  
            }  
        };  
          
    }  

manifest:

    <service android:name="com.zj.service.ServiceA">  
                <intent-filter>  
                    <action android:name="serviceA"></action>  
                </intent-filter>  
            </service>  

3、本地Service与Activity进行交互情况

Java Code:

    /** 
        (1). 添加了一个public内部类继承Binder,并添加getService方法来返回当前的Service对象; 
        (2). 新建一个IBinder对象——new那个Binder内部类; 
        (3). onBind方法返还那个IBinder对象。 
     */  
    public class ServiceB extends Service {  
      
        private final IBinder mBinder = new MyBinder();  
          
        public class MyBinder extends Binder{  
            public ServiceB getService(){  
                Log.i("service", "ServiceB.this "+ServiceB.this);  
                return ServiceB.this;  
            }  
        }  
          
        @Override  
        public IBinder onBind(Intent arg0) {  
            Log.i("service", "onBind...");  
            return mBinder;  
        }  
      
        @Override  
        public void onCreate() {  
            super.onCreate();  
            Log.i("service", "onCreate...");  
        }  
      
        @Override  
        public void onDestroy() {  
            super.onDestroy();  
            Log.i("service", "onDestroy...");  
        }  
      
        @Override  
        public void onStart(Intent intent, int startId) {  
            super.onStart(intent, startId);  
            //使用bindService()绑定service时,永远不会调用onStart()方法   
            Log.i("service", "onStart...");  
        }  
              
            //测试service向activity传递信息   
            public String getData(){  
                  return "hello android !";  
            }  
     }  

    public class MainActivity extends Activity {  
        private Button  bindBtn , unbindBtn , dataBtn;  
        private ServiceB mService;  
        private boolean isRegist;//判断service是否已经成功注册   
        private String name;  
        private ServiceConnection conn = new ServiceConnection() {  
              
            //断开连接时调用   
            @Override  
            public void onServiceDisconnected(ComponentName arg0) {  
                Log.i("service", "onServiceDisconnected...");  
            }  
            //连接时调用   
            @Override  
            public void onServiceConnected(ComponentName arg0, IBinder binder) {  
                mService = ((MyBinder)binder).getService();  
                Log.i("service", "onServiceConnected..."+mService);  
            }  
        };  
          
          
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.service_demo);  
            bindBtn = (Button) findViewById(R.id.bindBtn);  
            unbindBtn = (Button) findViewById(R.id.unbindBtn);  
            dataBtn = (Button)findViewById(R.id.getData);  
            bindBtn.setOnClickListener(listener);  
            unbindBtn.setOnClickListener(listener);  
            dataBtn.setOnClickListener(listener);  
        }  
          
        private OnClickListener listener = new OnClickListener() {  
            @Override  
            public void onClick(View view) {  
                Intent service = new Intent();  
                service.setAction("serviceB");  
                //向service传递值   
                service.putExtra("name", "i am service");  
                switch (view.getId()) {  
                case R.id.bindBtn:  
                    bindService(service, conn, Service.BIND_AUTO_CREATE);  
                    isRegist = true;  
                    break;  
                case R.id.unbindBtn:  
                    //如果没有先进行bindService就直接unbindService会抛出异常"Service not registered"   
                    if(isRegist){  
                        unbindService(conn);  
                        isRegist = false;  
                    }  
                    break;  
                case R.id.getData:  
                    //获取Service传递过来的值   
                    Toast.makeText(MainActivity.this, "service传递的值: "+mService.getData(), Toast.LENGTH_LONG).show();  
                    break;  
                default:  
                    break;  
                }  
            }  
        };  
          
    }  

Service : onCreate() → onBind() → Activity : onServiceConnected()  ; 可见onStart()是不会调用的!

4、远程Service与Activity的交互(AIDL的应用)

首先我们先上一个通俗的情景:在应用1中Activity绑定了一个Service,并且设置了一些值,此时我们想在应用2中调用该service并且想得到该值应该怎么做?我们都知道每个应用程序都运行在各自的进程中,并且android平台是不允许不同进程间进行直接的对象数据等传递的。如果必须进行跨进程之间的数据传递,那么我们就应该使用AIDL(Android Interface Definition Language)。

AIDL只支持方法,不能定义静态成员,并且方法也不能有类似public等的修饰符;AIDL运行方法有任何类型的参数和返回值,在java的类型中,以下的类型使用时不需要导入包(import),基本数据类型、String、Map、List.当然为了避免出错,建议只要使用了,就导入包。

使用AIDL的步骤:

服务端(提供服务):

第1步:定义一个*.aidl文件,该文件里是符合aidl语言规范的接口定义,里面定义了外部应用可以访问的方法。当我们保存该文件的时候,eclipse会自动为我们在gen文件夹下生成一个相应的java接口文件。如:

    package com.zj.service;  
    interface IPerson{  
        void setName(String name);  
        String getName();  
    }    

第2步:实现AIDL文件生成的JAVA接口Stub

public class PersonImpl extends IPerson.Stub {  
  
    private String name;  
  
    @Override  
    public String getName() throws RemoteException {  
        return name;  
    }  
  
    @Override  
    public void setName(String name) throws RemoteException {  
        this.name = name;  
    }  
      
} 

第3步:定义一个自己的service,    并将其注册到androidManifest.xml文件中,例如:

    public class ServiceC extends Service {  
        private Stub iPerson = new PersonImpl();  
        @Override  
        public IBinder onBind(Intent arg0) {  
            Log.i("service", "onBind...");  
            return iPerson;  
        }  
    }   

    <service android:name="com.zj.service.ServiceC">  
        <intent-filter>  
            <action android:name="forServiceAidl"></action>  
        </intent-filter>  
    </service>  

注意这里一定要提供一个intent-filter,我们的客户端进程就是通过该action访问到服务端进程的哦。

我们都知道,在实现自己的service时,为了其他应用可以通过bindService来和我们的service进行交互,我们都要实现service中的onBind()方法,并且返回一个继承了Binder的内部类;在这里,eclipse自动为我们生成的RemoteServiceInterface.java中有一个实现了Binder的内部类,RemoteServiceInterface.Stub。AIDL要求我们,在这里不能再直接去实现Binder类了,而是去实现,AIDL提供给我们的Stub类。 实现stub类的同时,AIDL还要求我们同时实现我们在接口中定义的各种服务的具体实现。至此为止,我们的服务端已经和我们的aidl文件绑定到一起了哦。

同一个应用中的Activity为该Service中赋值:

    public class MainActivity extends Activity {  
          
        private IPerson iPerson;  
        private Button bindBtn,unbindBtn;  
          
        private ServiceConnection conn = new ServiceConnection() {  
              
            //断开连接时调用   
            @Override  
            public void onServiceDisconnected(ComponentName arg0) {  
            }  
            //连接时调用   
            @Override  
            public void onServiceConnected(ComponentName arg0, IBinder binder) {  
                iPerson = IPerson.Stub.asInterface(binder);  
                if(iPerson!=null){  
                    try {  
                        iPerson.setName("Service AIDL");  
                        Toast.makeText(MainActivity.this, "赋值成功!", Toast.LENGTH_LONG).show();  
                    } catch (RemoteException e) {  
                        e.printStackTrace();  
                        Toast.makeText(MainActivity.this, "赋值失败!", Toast.LENGTH_LONG).show();  
                    }  
                }  
            }  
        };  
          
          
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.service_aidl);  
            bindBtn = (Button)findViewById(R.id.bindBtn);  
            unbindBtn = (Button)findViewById(R.id.unbindBtn);  
            bindBtn.setOnClickListener(listener);  
            unbindBtn.setOnClickListener(listener);  
        }  
          
        private OnClickListener listener = new OnClickListener() {  
            @Override  
            public void onClick(View view) {  
                switch (view.getId()) {  
                case R.id.bindBtn:  
                    //本应用中需要在manifest中配置RemoteService   
                    bindService(new Intent("forServiceAidl"), conn, Service.BIND_AUTO_CREATE);  
                    break;  
                case R.id.unbindBtn:  
                    unbindService(conn);  
                    break;  
                default:  
                    break;  
                }  
            }  
        };  
          
    }  

客户端:
       第1步:客户端要想使用该服务,肯定要先知道我们的服务在aidl文件中到底对外提供了什么服务,对吧?所以,第一步,我们要做的就是,将aidl文件拷贝一份到客户端的程序中(这里一定要注意,包路径要和服务端的保持一致哦,例如服务端为cn.com.chenzheng_java.remote.a.aidl,那么在客户端这边也应该是这个路径)。

      第2步:我们都知道,想要和service交互,我们要通过bindService方法,该方法中有一个ServiceConnection类型的参数。而我们的主要代码便是在该接口的实现中。

      第3步:在ServiceConnection实现类的onServiceConnected(ComponentName name, IBinder service)方法中通过类似remoteServiceInterface = RemoteServiceInterface.Stub.asInterface(service);方式就可以获得远程服务端提供的服务的实例,然后我们就可以通过remoteServiceInterface 对象调用接口中提供的方法进行交互了。(这里的关键是通过*.Stub.asInterface(service);方法获取一个aidl接口的实例哦)

       我们前面在服务端中说过了,必须提供一个intent-filter来匹配请求是否合法,所以我们在客户端访问服务的时候,还必须传递包含了匹配action的Intent哦。

客户端中使用服务端中的service范例:

    public class MainActivity extends Activity {  
      
        private IPerson person;  
        private Button btn;  
          
        private ServiceConnection conn = new ServiceConnection() {  
            @Override  
            public void onServiceDisconnected(ComponentName arg0) {  
            }  
            //因为有可能有多个应用同时进行RPC操作,所以同步该方法   
            @Override  
            public synchronized void onServiceConnected(ComponentName arg0, IBinder binder) {  
                //获得IPerson接口   
                person = IPerson.Stub.asInterface(binder);  
                if(person != null){  
                    try {  
                        //RPC方法调用   
                        String name = person.getName();  
                        Toast.makeText(MainActivity.this, "远程进程调用成功!值为 : "+name, Toast.LENGTH_LONG).show();  
                    } catch (RemoteException e) {  
                        e.printStackTrace();  
                        Toast.makeText(MainActivity.this, "远程进程调用失败! ", Toast.LENGTH_LONG).show();  
                    }  
                }  
            }  
        };  
          
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main);  
            btn = (Button)findViewById(R.id.btn);  
            btn.setOnClickListener(new OnClickListener() {  
                @Override  
                public void onClick(View arg0) {  
                    //该应用中不需要在manifest中配置RemoteService   
                    bindService(new Intent("forServiceAidl"), conn, Service.BIND_AUTO_CREATE);  
                }  
            });  
        }  
    }  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 12 中,C++ ServiceAIDLHAL 仍然是 Android 系统中重要的组成部分。 1. C++ Service C++ ServiceAndroid 系统中的一种基于 Binder 机制实现的服务。它可以在 Android 系统启动时启动,并提供某些系统级别的服务,例如音频服务、电源管理服务等等。 C++ Service 主要的实现语言是 C++,开发者可以使用 C++ 语言来编写自己的 C++ Service。要编写一个 C++ Service,开发者需要实现一个继承自 IInterface 的接口类,并在其中实现自己的服务逻辑。然后,开发者需要通过 ServiceManager 将自己的服务注册到系统中。 2. AIDL AIDLAndroid Interface Definition Language)是 Android 系统中的一种 RPC(Remote Procedure Call)框架,它可以用于在不同的进程之间进行通信。开发者可以使用 AIDL 来定义自己的接口,并通过 Binder 机制将接口暴露给客户端。 AIDL 语言是一种类似于 Java 的语言,开发者可以使用 AIDL 来定义自己的接口、数据类型和异常。在使用 AIDL 时,开发者需要编写一个 AIDL 文件,然后通过 AIDL 工具来生成对应的 Java 接口文件和 C++ 接口文件。在编写服务端和客户端时,开发者需要分别实现 Java 接口和 C++ 接口。 3. HAL HAL(Hardware Abstraction Layer)是 Android 系统中的一种硬件抽象层。它可以将硬件接口和实现分离,使得不同厂商可以实现自己的硬件适配层。开发者可以使用 HAL 来访问硬件设备,例如摄像头、传感器等等。 HAL 主要的实现语言是 C++,开发者可以使用 C++ 语言来编写自己的 HAL。要编写一个 HAL,开发者需要实现自己的 HAL 接口,并在其中实现自己的硬件逻辑。然后,开发者需要将自己的 HAL 注册到系统中,使得其他应用程序可以使用它。 以上就是 Android 12 中 C++ ServiceAIDLHAL 的一些基本介绍。这些技术都是 Android 系统中非常重要的组成部分,开发者需要深入了解它们的使用方法和原理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值