您的位置:首页 > 移动开发 > Android开发

Android服务Service详解(作用,生命周期,AIDL)系列文章--远程服务AIDL&IPC

2017-06-18 14:52 916 查看
本帖的地址:http://bbs.sunofbeaches.com/thread-5990-1-1.html

版权声明:本文为作者所有,未经作者允许不得转载。
Android服务Service详解(作用,生命周期,AIDL)系列文章--远程服务AIDL&IPC

其实前面的文章只是做铺垫的,哈哈,这里的话,需要给大家传授一些高级点的东西了哇!

首先,给大家解释一下前面的两个转有名词哈:
第一个AIDL:android interface defination language(安卓接口声明/定义语言)
第二个IPC:inter process communication(跨进程通讯)

首先,为什么要有跨进程通讯呢。我们都知道,在操作系统里头,每开启一个应用,就会有最少一个进程。而每个进程都是独立的,那它们之间怎么交流呢?对于操作系统来说,还有有挺多方法的,比如说:SD卡共享,但这效率低;信号量、消息邮箱或者消息队列之类的、socket也可以嘛。这是怎么回事呢,操作系统会分一块公共内存。在android里头这部分内存就叫binder,本质上就是共享内存。这个比共享SD卡的效率要高了吧!

这里面的话,我们要说的是跨进程间的服务通讯,也就是两个程序间的服务访问。先上例子吧:

我们创建一个项目为RemoteServiceDemo,这个应用的包名是:com.sunofbeaches.remoteservicedemo

然后,在这个程序里头,创建 一个服务:RemoteService,但是这个服务希望是远程调用的,所以的话,我们需要使用隐式意图来生命,在配置文件里头的话这样子写:

<service android:name=".RemoteService">
<intent-filter>
<action android:name="com.sunofbeaches.REMOTE_SERVICE"/>
</intent-filter>
</service>
然后创建一个AIDL接口:



然后把这个AIDL接口的内容修改了一个方法,调用远程服务内部方法。

package com.sunofbeaches.remoteservicedemo;
interface IRemoteService {

void callRemoteMethod();
}
搞定以后,点击菜单栏上的Build--->makeFile

然后,编写服务的代码,这里面这个内部代理类则要继承IRemoteService.stub。其实看它的原码就知道了,它是自动生成的,并且已经继承了Binder,服务具体的代码如下:

package com.sunofbeaches.remoteservicedemo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
im
4000
port android.util.Log;

/**
* Created by TrillGates on 17/4/17.
* God bless my code!
*/
public class RemoteService extends Service {

private static final String TAG = "RemoteService";

private class RemoteBinder extends IRemoteService.Stub {

@Override
public void callRemoteMethod() throws RemoteException {
innerMethod();
}
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "远程服务onBind方法被执行了....");
return new RemoteBinder();
}

@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "远程服务onCreate方法被执行了....");
}

@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "远程服务onUnbind方法被执行了....");
return super.onUnbind(intent);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "远程服务onStartCommand方法被执行了....");
return super.onStartCommand(intent, flags, startId);
}

public void innerMethod() {
Log.d(TAG, "远程服务内部方法被调用了....");
}
}
现在,我们就可以把这个应用跑起来了!

接着,我们在创建另外一个应用,它的MainActivity的布局是这样子的:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="bindRemote"
android:text="绑定远程服务"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="unbindRemote"
android:text="解绑远程服务"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="callRemote"
android:text="调用远程服务的方法"/>

</LinearLayout>

然后,把前面那个远程服务的AIDL文件夹,注意是整个文件夹,复制到当前目录的和AndroidManifest.xml同级文件夹下,这个是AndroidStudio工程哦。



大概目录如上嘛!
有了这些以后,我们就可以编写MainActivity的代码了:

package com.sunofbeaches.servicetestdemo;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import com.sunofbeaches.remoteservicedemo.IRemoteService;

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
private IRemoteService mRemoteService;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

}

/**
* 绑定远程服务
*
* @param view
*/
public void bindRemote(View view) {
Intent intent = new Intent();
intent.setAction("com.sunofbeaches.REMOTE_SERVICE");
intent.setPackage("com.sunofbeaches.remoteservicedemo");
bindService(intent, mConnection, BIND_AUTO_CREATE);
}

/**
* 接触远程服务的绑定
*
* @param view
*/
public void unbindRemote(View view) {
unbindService(mConnection);
}

/**
* 调用远程服务的方法
*
* @param view
*/
public void callRemote(View view) {
try {
mRemoteService.callRemoteMethod();
} catch (RemoteException e) {
e.printStackTrace();
}
}

private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemoteService = IRemoteService.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "服务断开连接....");
}
};

}

然后把程序跑起来!选择logcat 过滤为远程程序,这样子的 话才可以看到Log哦!



执行以下操作:

点击绑定远程服务

点击调用远程服务方法

点击解除远程服务绑定



是不是很简单呢!好了哈,到这里的话我们就已经学会了如何去跨进程地调用服务内部的方法。也许聪明的你就很好奇了!
这跨进程通讯有什么用呢?

比如说,我们暴露出API来,给第三方充值,对吧。支付宝,微信,这些都需要用到跨进程通讯的呢!

好啦,到这里服务系列的文章写完了,有空我再回来写博客!

下面是博主的联系方式,欢迎大家加入我们社区,阳光沙滩

网易云视频:





社区网站:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐