aidl使用采坑记详解手机开发

什么是AIDL?

AIDL是 Android Interface definition language的缩写,它是一种Android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口

AIDL可以解决什么问题?

  • 可以实现多个应用程序共享同一个Service的功能,比如:IM服务可以提供给多个APP使用,先在推送基本都是采取这种方案
  • 可以跨进程调用服务里的方法

搭建了简单的Service框架

1.继承Service

public class PushService extends Service{      @Nullable     @Override     public IBinder onBind(Intent intent) {         return null;     }      @Override     public boolean onUnbind(Intent intent) {         return super.onUnbind(intent);     } }

2.在AndroidManifest.xml里注册

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
          package="name.quanke.aidldemo"> 
 
    <application 
            android:allowBackup="true" 
            android:icon="@mipmap/ic_launcher" 
            android:label="@string/app_name" 
            android:name=".App" 
            android:supportsRtl="true" 
            android:theme="@style/AppTheme"> 
        <activity android:name=".MainActivity"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN"/> 
 
                <category android:name="android.intent.category.LAUNCHER"/> 
            </intent-filter> 
        </activity> 
 
        <service 
                android:name=".PushService" 
                android:enabled="true" 
                android:process=":push" 
                android:exported="true"> 
        </service> 
    </application> 
 
</manifest> 

建立AIDL

创建AIDL文件
aidl使用采坑记详解手机开发
编写AIDL文件
interface IHandler { 
  void connect(); 
}

aidl生成后的样子

aidl使用采坑记详解手机开发
编写客户端 ServiceConnection
public class PushClient { 
    private IHandler iHandler; 
    private static PushClient instance = new PushClient(); 
 
    public static PushClient getInstance() { 
        return instance; 
    } 
 
    public void init(Application app){ 
        Intent binderIntent = new Intent(app,PushService.class); 
        app.bindService(binderIntent, serviceConnection, Context.BIND_AUTO_CREATE); 
    } 
 
    private ServiceConnection serviceConnection = new ServiceConnection() { 
        @Override 
        public void onServiceConnected(ComponentName name, IBinder service) { 
            iHandler = IHandler.Stub.asInterface(service); 
            //连接成功调用 
        } 
 
        @Override 
        public void onServiceDisconnected(ComponentName name) { 
            //断开连接调用 
        } 
    }; 
 
    //通过AIDL远程调用 
    public void connect(){ 
        try { 
            iHandler.connect(); 
        } catch (RemoteException e) { 
            e.printStackTrace(); 
        } 
    } 
}

写服务端实现connect方法
public class LibHandler extends IHandler.Stub{ 
 
 
    @Override 
    public void connect() throws RemoteException { 
 
    } 
 
    @Override 
    public IBinder asBinder() { 
        return null; 
    } 
}

测试

public class MainActivity extends AppCompatActivity implements View.OnClickListener { 
    @Override 
    protected void onCreate(@Nullable Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        init(); 
    } 
 
    private void init() { 
      findViewById(R.id.aidl_test).setOnClickListener(this); 
    } 
 
    @Override 
    public void onClick(View view) { 
        PushClient.getInstance().connect(); 
    } 
}

其实到这里我们就结束了。

接下来我们看看如果自定义传递的数据类型

传递自定义的类型

AIDL默认支持的类型包括Java基本类型(int、long、boolean等),和(String、List、Map、CharSequence),如果要传递自定义的类型需要实现android.os.Parcelable接口。


自定义Message实体:

public class Message implements Parcelable { 
    private long id; 
    private String content; 
 
    public long getId() { 
        return id; 
    } 
 
    public void setId(long id) { 
        this.id = id; 
    } 
 
    public String getContent() { 
        return content; 
    } 
 
    public void setContent(String content) { 
        this.content = content; 
    } 
 
    @Override 
    public String toString() { 
        return "Message{" + 
                "id=" + id + 
                ", content='" + content + '/'' + 
                '}'; 
    } 
 
    @Override 
    public int describeContents() { 
        return 0; 
    } 
 
    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
        dest.writeLong(this.id); 
        dest.writeString(this.content); 
    } 
 
    protected Message(Parcel in) { 
        this.id = in.readLong(); 
        this.content = in.readString(); 
    } 
 
    public static final Creator<Message> CREATOR = new Creator<Message>() { 
        @Override 
        public Message createFromParcel(Parcel source) { 
            return new Message(source); 
        } 
 
        @Override 
        public Message[] newArray(int size) { 
            return new Message[size]; 
        } 
    }; 
 
}

修改IHandler

interface IHandler { 
  void connect(); 
  void sendMessage(Message message); 
}


aidl使用采坑记详解手机开发
注意: 自定类型aidl文件名字、路径需要和自定义类名字、路径保持一致,
 编译一下,发现报了个错
aidl使用采坑记详解手机开发
意思是必须定义Message的方向,AIDL 参数有方向。(学习了)
如果sendMessage方法的message参数是纯粹的输入参数—这意味着是从客户端到服务器的数据,你需要在AIDL声明:

void sendMessage(in Message message); 

如果
sendMessage
方法的
message
参数是纯粹的输出-这意味着它的数据是通过从服务器到客户端,使用:

void sendMessage(out Message message); 

如果
sendMessage
方法的
message
参数是输入也是输出-客户端的值在服务可能会修改,使用:

void sendMessage(inout Message message); 

我们这里是客户端范围服务端的数据,所以用in

interface IHandler { 
  void connect(); 
  void sendMessage(in Message message); 
}

好了,aidl的用法就到这里了,aidl主要是用在跨进程间通信和数据交换,平时开发中也用的比较少,通过这个例子加深了对他的用法,后面有什么好的坑,我会发出了的,谢谢大家。最后做个链接 

https://github.com/xiangzhihong/aidl

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/5986.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论