Android09_远程服务_系统服务_aidl

1.1,startService()的缺陷,不能直接调用服务的代码

startService()得不到服务的引用,因为服务是框架new出来的,Activiyi里面是得不到服务的引用.如果直接new 服务类,会出错:报空指针异常,无法获取上下文,自己new出来的服务得不到上下文,也就无法打印Toast信息.(Activity也不可以直接new)

 

1.2, bindService()绑定服务

可以间接的调用到服务里面的方法,可以与服务进行通讯(通过代理人间接的调用服务里面的方法,直接调用可能会出现风险(篡改数据?))

 

1.3 通过bindService()调用服务中的方法

①创建服务的类,配置信息....

onBind()方法返回communication channel to ther service 返回服务的通讯频道,在服务成功绑定的时候返回服务中的代理人(中间人)

②创建服务的代理人:

Public class MyBinder extends Binder(IBinder的实现类)/*implements (不推荐)IBinder(会实现大量方法)*/{

创建一个方法,在方法内调用服务类的方法

}

onBind()方法里返回中间人

③在Activity,启动服务的时候,接收中间人

Intent service = new Intent(xx,xx);

bindService(service,serviceConnection,flags)

;Service:意图对象

serviceConnection:通讯频道

Int flags:可选的标识:一般选BIND_AUTO_CREATE//如果绑定的服务不存在,就创建它

//创建一个实现类,实现ServiceConnection

//当服务被成功链接的时候调用

onServiceConnected(xx,IBinder(获得的是服务类中returnIBinder对象));

onServiceDisConnected()

注意:在这里可以定义一个成员变量来接收IBinder对象,然后可以在别的地方使用

 

1.4 绑定服务,调用服务方法的步骤

在服务类中

①编写服务代码,重写onBinder对象,返回自定义的IBinder对象

②在服务内部定义一个IBinder代理人对象(内部类)

③在代理人对象里创建一个方法,间接的调用服务里面的方法

Activity

①采用绑定的方法连接到服务

bindService(intent,new Myconn,BIND_AUTO_CREATE)

②在ServiceConnection的实现类中有一个方法,获取到服务类返回的代理人对象

onServiceConnected(xx,xx);

③强制类型转换,IBinder转成MyBinder类型

④调用代理人里面的方法,相当于间接的调用服务里面的方法

⑤取消绑定服务unbindService(conn对象)

注意:解除绑定的时候不能使用绑定服务new出来的conn.

2.通过接口隐藏代码内部实现的细节

①定义一个接口,接口内定义一个方法,方法名与要隐藏的方法名一致(参数一致)

②需要隐藏的类(私有的)去实现接口,通过接口把这个方法暴露出来

其实返回过来的对象,就是这个被隐藏的类的对象,但是不能直接使用这个类的对象,而要通过这个接口去接收它.父类引用指向子类对象,只能看到重写的方法.

 

3.绑定服务的生命周期

onBind()//绑定服务的时候调用

onUnBind()//解除服务的时候调用

onCreate()//第一次创建服务的时候调用

onStart()//已被废弃,但是还是可以用,通过startService()方法启动服务的时候调用

onStartCommand()//不会在绑定服务的时候调用

onDestory()//销毁的时候,解除服务的时候会调用

 

额外①:多次绑定服务,onBind(),onCreate()都只会被执行一次

②开发的时候,是不能多次绑定服务的,如果需要调用服务的方法,就绑定服务,只能绑定一次,服务只可以被解绑一次,多次解绑同一个conn对象,会抛出异常

所以绑定服务,解绑服务,就放在Acivity中的onCreate()onDestory()中即可

 

4.两种开启服务方式的区别

4.1采用Start的方式开启服务

服务一旦开启,就长期在后台运行,与开启者(Activity)没有直接的关系,开启者退出了,服务还是在后台长期运行,开启者不能直接调用(可以通过广播间接调用)服务里的方法.

start开启的服务,在系统设置界面里面可以观察到正在运行的服务

4.2 采用bindService的方式绑定服务

绑定服务,如果Activity退出了,服务也会一起销毁,同时可以通过中间人间接的调用服务里面的方法

在系统设置界面里面不可以观察到正在运行的服务

 

额外:①取消绑定服务之后还是可以继续调用方法,是因为虽然服务被销毁了,但是服务并不会立即被回收,所以中间人的引用对象还是继续存在,所以在销毁的时候,同时要把代理人对象重置为null;

②服务如果开启的同时被绑定,那么服务就停止不了,必须解除绑定才能停止服务.

③混合开启服务的应用:为了保证服务又能长期后台运行,又能调用到服务里面的方法,采用混合的方式开启服务.

请严格按照步骤混合方式编写代码:

start的方式开启服务(保证后台的长期运行)

bind的方式绑定服务(调用服务的方法)

unbind的方式解除绑定服务

stop的方式停止服务

这样出的BUG就比较少了

要注意的是,绑定服务是需要消耗时间的(异步的),不要在绑定之后马上就调用服务里面的方法,是有可能出现空指针异常的.

5.本地服务和远程服务

 

 

本地服务(local service):

服务代码在当前应用程序的内部

远程服务: remote service

服务的代码在另外一个应用程序里

①在远程服务类里,创建类继承service,清单文件配置,过滤器定义action标签,name属性自定义

②调用者的应用中,

创建意图对象,设置setAction(保持一致)

bindService(intent,conn,BIND_AUTO_CREATE);

创建自定义ServiceConntection继承类

③远程服务类中,反馈IBinder代理人,但是想要反馈接口,在调用者的代码里并没有他.

(可不可以通过反射获取?不可以,因为内存空间是相互独立的)

5.2 重要概念

①进程:操作系统分配的独立的内存空间

IPC:inter process communication 进程间通讯

操作系统在底层分配了一块公共空间(Binder驱动),当一方把数据放置在公共空间中,另一方就可以在公共空间中提取数据

aidl android interface definition language 安卓接口定义语言,用于进程间通信

 

5.3 aidl编程

①修改接口.java文件的后缀,aidl

②不需要权限修饰符,因为都是固定public

gen下会自动生成对应的java文件

④本地的代理人不再实现接口,而是继承接口中的内部类(这个类是自动生成的)

⑤调用者绑定远程服务,拷贝远程的规范(接口文件.aidl,包名要一致)

⑥在绑定成功的方法中,接口名.Stub.asInterface(service)

 

5.4 绑定远程服务调用服务方法的流程(远程服务是运行在子线程的,不能直接Toast提示)

①跟本地服务代码编写的流程是一致的,但是不能用显示意图调用(Class文件)而是通过隐式意图(设置Action动作调用)

②远程文件的接口定义文件,java-aidl

③把接口定义文件的访问权限全部删除,public,private

④原来的代理人extends IBinder implements 接口

  现在的代理人 extends 接口.Stub

⑤调用者先把远程服务.aidl文件拷贝到本地应用程序的工程目录里,包名要一致(包名可以看做是一把钥匙,Binder驱动空间中找到它的途径)

⑥接口引用= 接口引用.Stub.asInterface(service)得到远程服务的代理对象

⑦通过代理对象调用远程服务的方法

 

5.5 绑定远程服务的应用场景(远程支付)

 

6.1,案例,模拟支付宝安全支付练习

步骤①定义远程服务,配置清单文件action动作,重写onCreate()ondeStory()方法,定义一个方法实现支付提交的功能(用户名,密码,支付金额,账单),方法内部还有算法加密的操作,这里就不做了,也没有条件来做.最后返回数据结果

②其它操作,定义接口aidl文件,定义代理人.

③使用者,正常的远程调用服务即可.创建意图的时候不再指定classs文件,而是设置动作.再进行绑定服务的操作,其它的类同,调用方法,获取返回值.

(绑定远程服务一定要掌握,比较常见的有在索尼手机的底部有一个人脸识别的服务,可以通过绑定这个服务,把人脸的位置信息反馈至服务器.)

 

6.2 系统服务:

View.inflate()转换xmlview对象的操作,

底层就是调用了一个getStreamService()调用系统服务的操作.

Zygote(受精卵):安卓手机启动加载的第一个进程.

BatteryService :电池相关的服务

SensorService:传感器相关的服务

PowerManagerService-JNI:电源管理服务

PackgeManager:包管理服务

SystemServier:系统服务...........................................................................................

安卓开机的开机过程,就是一个个服务的开启.

 

要看安卓的源码,最好跑到内存里面观察代码的执行.然后通过内存中显示的类名查找源码.

 

6.3 利用系统服务监听通话的状态

①创建一个服务类,配置xml文件,重写onCraete(),onDestory()方法

②新的API TelephonyManager(这个类的实例要通过getStreamService(TELEPHONY_SERVICE)获取.)

tm.getCallState()//获得通话状态

  tm.getDeviceID()//获得入网许可id

  tm.getNetworkOperator()//得到运营商的名称

  tm.getNetworkType()//获得网络内容联通3G,移动3G之类

.....................

  Tm.listen(listener,PhoneStatusListener.LISTEM_CALL_STATE)//电话状态监听器

④创建一个类,继承PhoneStatusListener,自定义监听器

重写onCallStateChange(int state,incomingNumer(来电电话))方法

State:TelephoneManager.CALL_STATE_IDIE //空闲状态

CALL_STATE_RINGING//响铃状态

CALL_STATE_OFFHOOK//通过状态

⑤取消监听器:tm.listen(listener,null);

⑥需要添加权限READ_PHONE_STATE

 

6.4 多媒体录音机的开发

①添加权限:RECORD_AUDIO,WRITE_EXTERNAL_STORAGE(保存在存储卡中)

②拷贝文档的开始,结束录音功能

修改setAudioSource(MediaRecoder.AudioResource.MIC(这个只录了你的麦克风,)VOICE_CALL(上行下行的通话信息都录入,但是这个参数在很多手机上不生效,因为国外很多法律规定不能使用双向录音,但是华为手机支持,模拟器是不支持的))

mRecorder.setOutputStream(MediaRecorder.Outputformat.THREE.GPP)

setOutputFile(“文件名”)//SystemCLock.uptimeMills()获取系统时间

setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)//音频编码方式

注意:模拟器的音频有问题,长度有问题.

 

 private void startRecording() {
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mRecorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }

        mRecorder.start();
    }

    private void stopRecording() {
        mRecorder.stop();
        mRecorder.release();
        mRecorder = null;
    }

 

 

 

 

 

posted on 2016-06-01 23:32 抓根宝 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/adventurer/p/5551513.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中,要注册一个 AIDL 远程服务,需要完成以下几个步骤: 1. 定义一个 AIDL 接口,并在其中声明需要被客户端调用的方法。 2. 实现该 AIDL 接口,并在其中编写具体的业务逻辑代码。 3. 在服务端创建一个 Service,并将实现的 AIDL 接口绑定到该 Service 上。 4. 在 Service 的 `onBind()` 方法中,返回一个 `Binder` 对象,该对象实现了 AIDL 接口,并将其注册为远程服务。 5. 在 Manifest.xml 文件中注册该 Service。 下面是一个简单的示例,演示了如何注册一个 AIDL 远程服务: 1. 定义一个 AIDL 接口,例如 `ISampleAidlService.aidl`: ``` // ISampleAidlService.aidl package com.example.sampleaidlservice; // SampleData 数据结构 parcelable SampleData; // AIDL 接口 interface ISampleAidlService { // 获取 SampleData 对象 SampleData getSampleData(); } ``` 2. 实现该 AIDL 接口,例如 `SampleAidlServiceImpl.java`: ``` // SampleAidlServiceImpl.java package com.example.sampleaidlservice; import android.os.RemoteException; public class SampleAidlServiceImpl extends ISampleAidlService.Stub { @Override public SampleData getSampleData() throws RemoteException { SampleData data = new SampleData(); data.id = 1; data.name = "Sample Data"; return data; } } ``` 3. 在服务端创建一个 Service,并将实现的 AIDL 接口绑定到该 Service 上,例如 `SampleAidlService.java`: ``` // SampleAidlService.java package com.example.sampleaidlservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class SampleAidlService extends Service { private SampleAidlServiceImpl mService; @Override public void onCreate() { super.onCreate(); mService = new SampleAidlServiceImpl(); } @Override public IBinder onBind(Intent intent) { return mService; } } ``` 4. 在 Service 的 `onBind()` 方法中,返回一个 `Binder` 对象,该对象实现了 AIDL 接口,并将其注册为远程服务。 ``` // SampleAidlServiceImpl.java package com.example.sampleaidlservice; import android.os.RemoteException; public class SampleAidlServiceImpl extends ISampleAidlService.Stub { @Override public SampleData getSampleData() throws RemoteException { SampleData data = new SampleData(); data.id = 1; data.name = "Sample Data"; return data; } } // SampleAidlService.java package com.example.sampleaidlservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class SampleAidlService extends Service { private SampleAidlServiceImpl mService; @Override public void onCreate() { super.onCreate(); mService = new SampleAidlServiceImpl(); } @Override public IBinder onBind(Intent intent) { return mService; } } ``` 5. 在 Manifest.xml 文件中注册该 Service: ``` <!-- AndroidManifest.xml --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.sampleaidlservice"> <application ...> <service android:name=".SampleAidlService" android:exported="true"> <intent-filter> <action android:name="com.example.sampleaidlservice.ISampleAidlService" /> </intent-filter> </service> </application> </manifest> ``` 以上就是一个简单的 AIDL 远程服务的注册示例。在客户端可以通过 bindService() 方法来绑定该服务,并获取其中的方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值