跨app调用Service

一、项目要求

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

三、项目源代码

Programming-Learning-Process/Android学习 at main · cx1768762017/Programming-Learning-Process (github.com)

四、编写项目过程中的报错(主要是修改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"
}
相关推荐
松仔log1 小时前
Java中级——组合和继承
android·java·开发语言
我命由我123454 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian2335 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
2601_955759626 小时前
ClaudeAPI成本中心与业务标签设计指南
android·java·数据库
余衫马6 小时前
2026最新版!Android Studio 极速安装与配置指南
android·ide·android studio
AFinalStone6 小时前
Android 7系统异常问题排查(五)Framework层(下)—System Server崩溃
android·tombstone·系统异常
AFinalStone6 小时前
Android 7系统异常问题排查(八)系统追踪—Trace机制与性能诊断
android·系统异常
极客猴子10 小时前
Android录音转写频繁卡顿?多款APP长时间会议场景稳定性实测
android·人工智能·智能手机·飞书
Kapaseker10 小时前
Boolean 变量到底该怎么命名?
android·kotlin
AFinalStone10 小时前
Android 7系统异常问题排查(六)应用异常(上)—ANR机制全解
android·系统异常