Android aidl简单使用2

Android  2023年8月28日 am8:08发布1年前 (2023)更新 城堡大人
121 0 0

前言

之前记录AndroidAIDL使用,这次就多个进程绑定同一个AIDL服务,其实跟之前一样,只不过是进行了多次绑定而已。

流水账,可以不用看

正文

存在如下模块和lib库

# lib库
BiuMoreAidl
# 模块(客户端和服务端)
BiuMoreAidlClent
BiuMoreAidlService

客户端里两个Activity,但不同进程。

BiuMoreAidl

lib库中就公用的aidl的定义

// IMedia.aidl
package com.biumall.aidl;
interface IMedia {
        void previous();
        void play();
        void pause();
        void next();
}

build.gradle中添加

buildFeatures{aidl true}

BiuMoreAidlService

这里需要引入BiuMoreAidl

startService(new Intent(this, AidlService.class));
build.gradle
dependencies {
    implementation project(":BiuMoreAidl")
}
AndroidManifest.xml

这里是服务配置,配置了一个Action,方便用于启动服务。

<service
    android:name=".AidlService"
    android:exported="true">
    <intent-filter>
        <action android:name="com.biumall.service.AidlService" />
    </intent-filter>
</service>
ServiceApp.java

这里开启服务

public class ServiceApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        startService(new Intent(this, AidlService.class));
    }
}
MediaBinder.java

MediaBinder是实现IMedia.aidl接口

public class MediaBinder extends IMedia.Stub {
    private int mCount = 0;
    public void onStart() {
    }
    public void onStop() {
    }
    @Override
    public void previous() throws RemoteException {
    }
    @Override
    public void play() throws RemoteException {
    }
    @Override
    public void pause() throws RemoteException {
        mCount++; //每次调用增加异常
    }
    @Override
    public void next() throws RemoteException {
    }
}

除了实现IMedia.aidl接口,还是薪资两个方法onStart()和onStop(),用于初始化和关闭资源,这里暂时不做啥、

AidlService.java

后台服务,用于被客户端绑定,并返回MediaBinder的。

public class AidlService extends Service {
    private MediaBinder mMediaBinder;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mMediaBinder;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        mMediaBinder = new MediaBinder();
        mMediaBinder.onStart();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (null != mMediaBinder) {
            mMediaBinder.onStop();
        }
        mMediaBinder = null;
    }
}

BiuMoreAidlClent

客户端就分两个Activity不同进程中进行绑定服务。

build.gradle

也需要引入BiuMoreAidl

dependencies {
    implementation project(":BiuMoreAidl")
}
AndroidManifest.xml
<activity
    android:name="com.biumall.client.MainActivity"
    android:exported="true"
    android:launchMode="singleInstance">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity
    android:name="com.biumall.client.TwoActivity"
    android:exported="true"
    android:launchMode="singleInstance"
    android:process=":another_process">
</activity>

android:process=":another_process"这可以说可以开启新的进程。

ClientApp.java
public class ClientApp extends Application {
    @SuppressLint("StaticFieldLeak")
    private static Context mContext = null;
    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
    }
    public static Context getContext() {
        return mContext;
    }
}
MainActivity.java

PS: TwoActivity跟MainActivity一样,这里就不附上了

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private IMedia mIMedia;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initUI();
        bindService();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService();
    }
    private void bindService() {
        if (null == mIMedia) {
            Intent intent = new Intent();
            //需要指定绑定包名,不可以匿名绑定服务
            intent.setPackage("com.biumall.service");
            intent.setAction("com.biumall.service.AidlService");
            boolean bind = ClientApp.getContext().bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        }
    }
    private void unbindService() {
        if (null != mIMedia) {
            ClientApp.getContext().unbindService(mServiceConnection);
            mIMedia = null;
        }
    }
    private void initUI() {
        findViewById(R.id.main_bt_go_other).setOnClickListener(this);
        findViewById(R.id.main_bt_pause).setOnClickListener(this);
        findViewById(R.id.main_bt_play).setOnClickListener(this);
        findViewById(R.id.main_bt_previous).setOnClickListener(this);
        findViewById(R.id.main_bt_next).setOnClickListener(this);
    }
    private final ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIMedia = IMedia.Stub.asInterface(service);
            try {
                mIMedia.asBinder().linkToDeath(new IBinder.DeathRecipient() {
                    @Override
                    public void binderDied() {
                        //binderDied
                    }
                }, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mIMedia = null;
        }
    };
    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View v) {
        try {
            switch (v.getId()) {
                case R.id.main_bt_go_other:
                    Intent intent = new Intent(MainActivity.this, TwoActivity.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    ClientApp.getContext().startActivity(intent);
                    break;
                case R.id.main_bt_previous:
                    if (null != mIMedia) {
                        mIMedia.previous();
                    }
                    break;
                case R.id.main_bt_next:
                    if (null != mIMedia) {
                        mIMedia.next();
                    }
                    break;
                case R.id.main_bt_pause:
                    if (null != mIMedia) {
                        mIMedia.pause();
                    }
                    break;
                case R.id.main_bt_play:
                    if (null != mIMedia) {
                        mIMedia.play();
                    }
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
activity_main.xml
<?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:background="@android:color/background_dark"
    android:gravity="center"
    android:orientation="vertical">

    <Button
        android:id="@+id/main_bt_go_other"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:text="GoTo Two"
        android:textSize="30sp" />

    <Button
        android:id="@+id/main_bt_play"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:text="Play"
        android:textSize="30sp" />

    <Button
        android:id="@+id/main_bt_pause"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:text="Pause"
        android:textSize="30sp" />

    <Button
        android:id="@+id/main_bt_previous"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:text="Previous"
        android:textSize="30sp" />

    <Button
        android:id="@+id/main_bt_next"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:text="Next"
        android:textSize="30sp" />

</LinearLayout>

小结

同一个服务,可以被多次绑定,然后真正功能实现者在MediaBinder中。

参考文章

  1. Android aidl简单使用

 历史上的今天

  1. 2020: Android动画之TranslateAnimation使用(0条评论)
  2. 2019: 林清玄:把时间花在心灵上(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

WordPress博客搬家教程

这是建站的必备知识,我们需要怎么进行网络搬家,如果你不会,请仔细研读。这一篇文章写得最简单最明白的。第一步:备份网站根目录下所有文件并转移到新主机。这一步主要是把原来的空间中的网站程序、图片等资源下载备份,并上传到新的主机空间。如果原来空间支持在线压缩,并且新的空间支持解压缩,那么建议...

Kotlin字符串

前言简单记录一下Kotlin字符串。主要是方便自己查阅。正文字符串一个字符串可以包含一个或者多个字符,也可以不包含任何字符,即长度为0。var mString: String = "谷歌一下"var mString2 = "百度一下"遍历字符串遍历也是很多种,下面列举验证过的遍历...

顾城:门前

我多么希望,有一个门口早晨,阳光照在草上 我们站着扶着自己的门扇门很低,但太阳是明亮的 草在结它的种子风在摇它的叶子我们站着,不说话就十分美好 有门,不用开开是我们的,就十分美好

ThreadPoolExecutor简单记录

前言线程经常用,线程池也用,但在于如何使用,没有记录一下。本文参考别人文章整理。正文使用线程池的好处降低内存资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度。在线程池中的线程都是已经被创建好的,我们的任务直接获取一个空闲的线程就能够被执行了提高线程的可管...

莫言:陪女儿高考

那天晚上,带着书、衣服、药品、食物等诸多在这三天里有可能用得着的东西,搭出租车去赶考。我们很运气,女儿的考场排在本校,而且提前在校内培训中心定了一个有空调的房间,这样既是熟悉的环境,又免除了来回奔波之苦。信佛的妻子说这是佛祖的保佑啊!我也说,是的,这是佛祖的保佑。坐在出租车上,看到车牌照上的号码尾...

MediaPlayer java层介绍

前言Android中经常用MediaPlayer控制音频/视频文件和流的播放。虽然经常用,但没怎么看其源码,今天有空记录一下,方便自己查阅。正文本篇涉及的源码目录frameworks\base\media\java\android\media\MediaPlayer.javaPS:只是...