zoukankan      html  css  js  c++  java
  • Service与Activity与交流AIDL

      深圳旅游月。终于回来了,做了很多个月,这些天来的东西会慢慢总结出来的。今天,我们正在谈论的Service小东西:沟通。

    固定通信的做法比较,基本上按照写模板可以实现。

    1、Service与Activity沟通

        Activity通过startService()方法启动Service之后,Service将独立于Activity执行(尽管仍然是同一个进程),Activity无法指导Service怎样执行。当Activity须要依据一些条件决定Service怎样执行的时候。就须要有另外的方法了:将Service申明为远程Service。

        (1)、声明

        将一个服务声明为远程服务仅仅需在manifest文件的声明中加一句process=":remote"。例如以下所看到的:

    <service
    	android:name="com.iflytek.service.PowerService"
    	android:process=":remote" >
    </service>   
    

    (2)Service端

    private MyBinder mBinder= new MyBinder();
    
    public IBinder onBind(Intent intent){
    	return mBinder;
    }
    
    public MyBinder extends Binder{
    	public void doSomething(){
    		Log.d("Timothy", "I am doing something!")
    	}
    }

        onBind()方法在创建Service的时候就已经默认创建了,这里仅仅是实现了这种方法。mBinder就像是一座桥梁,连接了Service与Activity。将Service中的接口方法暴露给Activity,让Activity能够通过mBinder去调用这些接口。

    (3)Activity端

    private MyService.MyBinder myBinder;
    
    private ServiceConnection connection = new ServiceConnection(){
    	@Override
    	public void onServiceDisconnected(ComponentName name){
    	
    	}
    	
    	@Override
    	public void onServiceConnected(ComponentName name, IBinder service){
    		myBinder = (MyService.MyBinder)service;
    		myBinder.doSomething();
    	}
    }
    
    Intent bindIntent = new Intent(this, MyService.class);
    
    bindService(bindIntent, connection, BIND_AUTO_CREATE);
    
        首先是声明一个MyBInder类。让Activity能够使用这座桥梁。然后就是声明一个ServiceConnection对象。绑定的时候怎样调用Service的方法。最后就是绑定了。

        须要说明一点:bindService()函数的第三个參数说明。当绑定服务的时候,将自己主动调用Service的onCreate()方法。

        当须要多次调用doSomething()方法的时候,假设直接bindService是会报错的。这时候能够在bind之前加上以下这种一段:

    try{
        unbindService(connection);
    }catch(Exception e){
        e.printTrace();
    }
        这样就不会报错了。

    2、AIDL

        我在开发中遇到的问题是:应用层app须要在一定的条件下调用系统的休眠和关机。而休眠和关机的接口仅仅有系统级应用才干调用,这样就必须在系统层为应用提供可以远程调用的服务了。

        上面说的远程服务,实际上依旧是在同一个project中,可是我面对的问题非常明显,是全然独立的两个应用,怎么样才干在project1的类中引用到project2中的类呢?

        Google为此提供了一个叫做AIDL的东西。也就是Android Interface Describe Language。用这个东东作为调用的桥梁。

    关于AIDL的理论这里不多说。在此仅仅介绍其使用方法。

        (1)Service端

        a、首先是改动manifest文件:
    <service
        android:name="com.iflytek.service.PowerService"
        android:process=":remote" >
        <intent-filter>
            <action android:name="com.iflytek.vbox.power" />
        </intent-filter>
    </service>

        这东西看上去非常像Broadcast Receiver的声明,推測其内部实现也应该和广播差点儿相同。

        b、新建一个package,在package中新建AIDL文件。声明好Activity与Service通信的方法:

    package com.***.aidl;
    
    interface MyService{
    	void goToSleep();
    	void shutDown();
    } 
        注意这里不能用public、private修饰。编写好保存之后,将在gen文件夹下自己主动生成一个Java文件,这个文件不须要维护。

       c、改动PowerService文件,实现上面声明的接口。

    public class PowerService extends Service {
    	MyService.Stub mBinder;
    	PowerManager pm;
    	String filePath;
    	Handler handler;
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		// TODO Auto-generated method stub
    		return mBinder;
    	}
    
    	@Override
    	public void onCreate() {
    		super.onCreate();
    		
    		mBinder = new Stub() {
    			@Override
    			public void goToSleep() throws RemoteException {
    				Tools.writeLog("PowerService.goToSleep() is called");
    				pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    				SleepThread sleepThread = new SleepThread(pm);
    				sleepThread.start();
    			}
    
    			@Override
    			public void shutDown() throws RemoteException {
    				ShutDownThread shutDownThread = new ShutDownThread();
    				shutDownThread.start();
    			}
    		};
    	}
    }
       这里就是用mBinder实现了接口。

    接口中我启动了子线程去做真正的运行工作。这也是比較常见的使用方法。这里写法比較固定。照抄就好。


        (2)Activity端

        a、将Service中的AIDL连package一起复制过来,记得,是要连package一起。

        b、開始抄吧

    private MyService myService;
    private static ServiceConnection sleepConnection;
    private static ServiceConnection shutdownConnection;
    
    sleepConnection = new ServiceConnection() {
    	@Override
    	public void onServiceConnected(ComponentName arg0, IBinder arg1) {
    		Log.d("Timothy", "sleepConnection connected");
    		myService = MyService.Stub.asInterface(arg1);
    		try {
    			myService.goToSleep();
    		} catch (RemoteException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    	@Override
    	public void onServiceDisconnected(ComponentName arg0) {
    
    	}
    };
    
    shutdownConnection = new ServiceConnection() {
    	@Override
    	public void onServiceConnected(ComponentName arg0, IBinder arg1) {
    		Log.d("Timothy", "shutdownConnection");
    		myService = MyService.Stub.asInterface(arg1);
    		try {
    			myService.shutDown();
    		} catch (RemoteException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    	@Override
    	public void onServiceDisconnected(ComponentName arg0) {
    
    	}
    };
    
    Intent sleepIntent = new Intent("com.***.***.power");
    bindService(sleepIntent, sleepConnection, BIND_AUTO_CREATE);
    
    Intent updateIntent = new Intent("com.***.***.power");
    bindService(updateIntent, updateConnection, BIND_AUTO_CREATE);
    
        能够看到,这里和上面的远程服务差的不多,也是在bind的时候调用Service的方法。

        细致看看上面的写法,你就会发现AIDL的精妙之处就在于:1、将远程接口声明在本地,这样就能像本地类一样调用远程方法。符合Java的语法规则。2、使用类似于广播的机制启动远程的服务,并调用该方法。



    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    python得到今天前的七天每天日期
    python 实现元组中的的数据按照list排序, python查询mysql得到的数据是元组格式,按照list格式对他们排序
    NoReverseMatch at /salesman/zhuce/ Reverse for '/zhuce/' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
    为什么springMVC和Mybatis逐渐流行起来了?
    图像的七个不变矩 可用于图像的匹配
    【可视化必备】大数据时代的可视化工具
    常用机器视觉工具----图像分析工具(blob分析)
    【转】七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)
    C#编写滤镜 图片色调取反效果(Invert)
    Bitmap四种属性
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4805593.html
Copyright © 2011-2022 走看看