Android进程通信之AIDL

Android 进程通信(AIDL)

通过一段时间的学习,对AIDL有了一个初步的认识,最终实现了通信功能,以免忘记特此记录。

介绍:

利用AIDL(Android Interface Definition Language)实现APP间的通信(同一个手机上两个APP之间的通信),通过下列方法可以实现ClientAPP发送信息,ServerAPP接收信息。所以需要开发两个APP。

思路:

AIDL的实现思路是在ServerAPP上配置好AIDL相关信息以及相关的Service,让ClientAPP去绑定ServerAPP的服务,通过ServerAPP中的onBind返回AIDL的控制接口,然后就可以在ClientAPP中操作相关方法和ServerAPP进行通信。

两个APP都需要的配置:

1. 设置序列化对象Info.java实现 Parcelable,内容我们只传一句话,更多的自己去实现(代码1)
2. 配置AIDL相关文件Info.aidl MessageCenter.aidl,Info.aidl和Info.java需要同一个路径名(代码2)
3. 在build.gradle文件android{}中添加文件路径,以免aidl和java文件相互寻找不到(代码3)

ClientAPP需要的配置:

1. 与服务端建立连接(代码4)
2. 添加点击事件,调用服务端的方法(代码5)

ServerAPP需要的配置:

1. 配置AIDLService文件(代码6)
2. 在manifest.xml文件中配置Service(代码7)
3. 在MainActivity中启动Service(代码8)

注意:如果实现不了通讯,问题无非两种

1. AIDL和java文件的路径配置问题,有问题可以BD,网上很多解决方法
2. 绑定Service出现问题,就是ClientAPP没有绑定到ServerAPP的service
intent.setAction()和intent.setPackage()的设置出现问题

代码1:

public class Info implements Parcelable {
    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Info() {
    }

    public Info(Parcel in) {
        content = in.readString();

    }

    public static final Creator<Info> CREATOR = new Creator<Info>() {
        @Override
        public Info createFromParcel(Parcel in) {
            return new Info(in);
        }

        @Override
        public Info[] newArray(int size) {
            return new Info[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(content);

    }

    public void readFromParcel(Parcel dest) {
        //注意,此处的读值顺序应当是和writeToParcel()方法中一致的
        content = dest.readString();

    }

    @Override
    public String toString() {
		//打印做成Json格式
        return "Info"+"{"+"content:"+content+"}"
    }
}

代码2:

Info.aidl文件:
package com.clearliang.myaidlclient;
parcelable Info;//引入序列化的类

MessageCenter.aidl文件:
package com.clearliang.myaidlclient;
import com.clearliang.myaidlclient.Info;
interface MessageCenter {
    //所有的返回值前都不需要加任何东西,不管是什么数据类型
    List<Info> getInfo();
    //传参时除了Java基本类型以及String,CharSequence之外的类型
    //都需要在前面加上定向tag,具体加什么量需而定
    Info addInfo(inout Info info);
}

代码3:

sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java', 'src/main/aidl']
            resources.srcDirs = ['src/main/java', 'src/main/aidl']
            aidl.srcDirs = ['src/main/aidl']
            res.srcDirs = ['src/main/res']
            assets.srcDirs = ['src/main/assets']
        }
}

代码4:

//尝试与服务端建立连接
private void attemptToBindService() {
    Intent intent = new Intent();
    intent.setAction("com.clearliang.myaidlserver");
    intent.setPackage("com.clearliang.myaidlserver");//应用包名
    bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}

private ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.e(getLocalClassName(), "service connected");
        messageCenter = MessageCenter.Stub.asInterface(service);//拿到ServerAPP的AIDL控制接口
        mBound = true;

        if (messageCenter != null) {
            try {
                mInfoList = messageCenter.getInfo();
                Log.e(getLocalClassName(), mInfoList.toString());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.e(getLocalClassName(), "service disconnected");
        mBound = false;
    }
};

注意:别忘了在onStop中解绑服务unbindService(mServiceConnection);

代码5

public void addMessage(String content) {
    //如果与服务端的连接处于未连接状态,则尝试连接
    if (!mBound) {
        attemptToBindService();
        Toast.makeText(this, "当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show();
        return;
    }
    if (messageCenter == null) return;

    Info info = new Info();
    info.setContent(content);
    try {
        messageCenter.addInfo(info);
        Log.e(getLocalClassName(),"客户端:"+ info.toString());
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

代码6

public class AIDLService extends Service {
    public final String TAG = this.getClass().getSimpleName();

    private List<Info> messages = new ArrayList<>();

    private final MessageCenter.Stub messageCenter = new MessageCenter.Stub() {
        @Override
        public List<Info> getInfo() throws RemoteException {
            synchronized (this) {
                Log.e(TAG, "getInfo invoking getInfo() method , now the list is : " + messages.toString());
                if (messages != null) {
                    return messages;
                }
                return new ArrayList<>();
            }
        }

        @Override
        public Info addInfo(Info message) throws RemoteException {
            synchronized (this) {
                if (messages == null) {
                    messages = new ArrayList<>();
                }
                if (message == null) {
                    Log.e(TAG, "message is null in In");
                    message = new Info();
                }

                if (!messages.contains(message)) {
                    messages.add(message);
                }

                Log.e(TAG, "客户传来了数据" + messages.toString());
                Info mInfo = new Info();
                mInfo.setContent("服务端做了修改:" + message.getContent() + "time:" + (System.currentTimeMillis()));
                return mInfo;
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(getClass().getSimpleName(), String.format("on bind,intent = %s", intent.toString()));
        return messageCenter;//这里给ClientAPP提供AIDL管理接口的返回
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

代码7

<service
    android:name=".AIDLService"
    android:exported="true">
    <intent-filter>
        <action android:name="com.clearliang.myaidlserver"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</service>

代码8

public class MainActivity extends AppCompatActivity {
    private Intent intent;

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

        intent=new Intent(this,AIDLService.class);
        startService(intent);
    }

	//别忘了停止服务
    @Override
    protected void onDestroy() {
        super.onDestroy();
        intent = new Intent(this,AIDLService.class);
        stopService(intent);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值