一、项目要求
1、在Model app中创建一个服务 QueryWeekdayService,该服务提供一个公共方法 QueryWeekday,输入参数日期(年、月、日),返回该日期是星期几。要求本应用程序和其它应用程序都能够绑定到该服务,并调用公共方法。
2、在Model app2中创建一个应用程序app2,验证1中创建的服务。
二、项目步骤
1、在Model app中创建service:
1)新建AIDL文件
(1)修改build.gradle文件,在Android中添加属性:
buildFeatures{aidl true},如果不添加的话将无法创建AIDL文件
(2)创建AIDL文件
在包中,new--->AIDL--->AIDL file
创建结果:
(3)声明想要远程调用的接口
(4)点击 Build-->Rebuild Project,从而将接口文件自动生成为java文件
创建结果:
2)写Service文件(这一步和写本地Service有点不同)
(1)声明并实现一个IBinder对象(这里与一般的bindService不同),这里就是实例化你刚刚定义的接口
java
private final IBinder mBinder = new IMyAidlInterface.Stub(){
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {}
@Override
public String remoteGetWeekday(String date) throws RemoteException {
return getWeekday(date); //调用具体的业务
}
};
(2)绑定你的接口
java
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
(3)写具体的业务
java
public String getWeekday(String date){
String[] dates = date.split("-");
String[] weekdays = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六",};
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR,Integer.parseInt(dates[0]));
cal.set(Calendar.MONTH,Integer.parseInt(dates[1])-1);
cal.set(Calendar.DATE,Integer.parseInt(dates[2]));
int weekday = cal.get(Calendar.DAY_OF_WEEK)-1;
return date+"的那天是"+weekdays[weekday];
}
(4)在Model app中创建一个activity MainActivity,用于检测功能
下面附上各个模块的功能以及代码:
onCreate():程序启动时会调用此方法,进行相关的初始化设置,如加载界面布局文件,获取查询按钮和日期输入框的实例,以及设置查询按钮的点击事件。
onStart():当Activity启动或重新可见时,会调用此方法,这里主要是绑定远程服务,使用bindService()
方法,将创建的Intent和ServiceConnection对象传入,通过后台自动创建服务的方式进行绑定。
onStop():当Activity停止时,会调用此方法,这里主要是解绑远程服务,防止Activity销毁后,服务还持有Activity的引用,导致内存泄露。
java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button queryBtn = (Button)findViewById(R.id.queryBtn); // 获取查询按钮
EditText dateText = (EditText)findViewById(R.id.dateEditView); // 获取日期输入框
queryBtn.setOnClickListener(v -> {
String date = dateText.getText().toString().trim(); // 获取输入的日期
String weekday = null;
try {
weekday = queryWeekday.remoteGetWeekday(date); // 调用远程服务的方法获取星期
} catch (RemoteException e) {
e.printStackTrace();
}
Toast.makeText(this,weekday,Toast.LENGTH_LONG).show(); // 显示结果
});
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this,QueryWeekday.class); // 创建一个Intent对象,用于指定要绑定的服务
Boolean result = bindService(intent,conn,BIND_AUTO_CREATE); // 绑定服务,并返回绑定结果
Log.i("result",result+"");
}
@Override
protected void onStop() {
super.onStop();
unbindService(conn); // 解绑服务
}
ServiceConnection conn:这是一个服务连接对象,当服务连接成功时,会回调其onServiceConnected()方法,然后通过IMyAidlInterface.Stub.asInterface(service)获取远程服务的接口实例,以便进行后续的通信。当服务断开连接时,会回调其onServiceDisconnected()方法。
java
private final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
queryWeekday = IMyAidlInterface.Stub.asInterface(service); // 获取远程服务的接口实例
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
3)检查Service功能是否正常
2、在ModelB中调用ModelA中的service
1)创建AIDL文件
在同一个项目下新建一个Model app2,然后参照上面的步骤创建一个AIDL文件。需要注意的是,必须保证包名一致。
2)在Model app2中添加依赖
(1)修改Model app2的build.grade
(2)修改Model app的builder.grade
重构项目:
(3)编写Activity
Model app2的activity的代码和Model app的activity代码差不多,就不再赘述了
3、运行Model app2的Activity
三、项目源代码
四、编写项目过程中的报错(主要是修改build.grade)
1、Model app2添加Model app的依赖后rebuild的时候报错,但是sync的时候没有报错
这个问题可以通过修改Model app的build.grade中的plugins属性解决,将其从
bash
plugins {
id 'com.android.application'
}
改成:
bash
plugins {
id 'com.android.library'
}
2、完成上述修改后,sync的时候报错:
rebuild的时候报错:
这个问题可以通过修改Model app的build.grade中的defaultConfig的applicationId属性解决,将其从:
arduino
defaultConfig {
applicationId "com.example.week_11_experiment_2"
minSdk 24
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
改成:
perl
defaultConfig {
// applicationId "com.example.week_11_experiment_2"
minSdk 24
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}