您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
65_采用aidl访问远程服务里面的方法
发布时间:2021-03-08 17:21:29编辑:雪饮阅读()
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.remoteservice">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Remoteservice">
<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=".RemoteService" >
<intent-filter >
<action android:name="com.example.remoteservice"/>
</intent-filter>
</service>
</application>
</manifest>
Ibinder绑定接口返回以一个可以提供对外开放本服务中一个方法的实例并实现该实例的类,在这个类中覆写调用远程的方法(调用远程的方法需要以另外一个接口存在,让该类来实现)
RemoteService.java:
package com.example.remoteservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class RemoteService extends Service {
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
private class MyBinder extends IService.Stub{
@Override
public void callMethodInService() throws RemoteException {
sayHelloInService();
}
}
/**
* 服务里面的一个方法
*/
public void sayHelloInService(){
System.out.println("服务 remote hello in service");
}
@Override
public void onCreate() {
System.out.println("服务 remote service oncreate");
super.onCreate();
}
}上面所需要依赖的另外一个接口IService.aidl:
package com.example.remoteservice;
interface IService {
void callMethodInService();
}其实就是一个.java文件,直接修改后缀为aidl
这个aidl文件在老的sdk,至少是安卓9之前吧,直接把这个文件和本项目的主activity对应的java文件,例如MainActivity.java于同目录中,至少安卓9现在不是这样了
安卓9中其包名要保持和上面清单文件中意图的name要保持一致,另外存储路径也是在main下建立aidl目录,然后建立package和上面清单文件中相同的名称做为package的名称,然后才将这个aidl文件放到这个新建立的包里面,那么路径如:
如果项目中还出现这个aidl对应的java类报红色状态错误时候,则可以尝试clean project/rebuild project
那么远程服务端就只剩下主activity的java程序MainActivity.java就显示一个界面而已,没什么特殊之处:
package com.example.remoteservice;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}远程服务调用端搭建
搭建好了远程服务,那么接下来就需要搭建远程服务调用端,也就是客户端了。
最基础的布局也需要一个按钮,通过点击这个按钮来调用远程服务activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="调用远程服务"
android:onClick="click"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>然后是这个按钮的点击事件的具体实现了MainActivity.java:
package com.example.callremoteservice;
import androidx.appcompat.app.AppCompatActivity;
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.view.View;
import com.example.remoteservice.IService;
public class MainActivity extends AppCompatActivity {
IService iService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
//在安卓5.0以后,采用隐式启动时,会出现java.lang.IllegalArgumentException: Service Intent must be explicit异常。也就是说Service的Intent必须明确。
//解决方法就是给Intent设置一下具体的包名,指明具体是哪个包启动的Service。在这里当然是远程服务端的包名了
intent.setPackage("com.example.remoteservice");
intent.setAction("com.example.remoteservice");
bindService(intent, new MyConn(), BIND_AUTO_CREATE);
}
public void click(View view){
try {
// 调用了远程服务的方法
iService.callMethodInService();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private class MyConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iService = IService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}
}接下来同样是这个aidl文件,同服务端一样的路径、包名等IService.aidl:
package com.example.remoteservice;
interface IService {
void callMethodInService();
} 调用远程服务里面的方法
当服务端与客户端都建立好之后,先部署服务端(安装成功即可),然后部署客户端,服务端和客户端都部署到一个设备中,然后打开服务端的日志猫,有必要可以写个过滤规则。然后打开客户端点击调用远程服务,就可以看到服务端日志猫里面有之前我们代码里面打印向服务端中的日志了。那么就没有问题了,ok了。
关键字词:aidl,android,服务