Android aidl 简单小demo学习过程记录(菜鸟详细版,快速上手aidl)

Android aidl 简单小demo学习过程记录(菜鸟详细版,快速上手aidl)

  • 必须看!!!,要不回头发现文章没啥用请别骂!!
  • 概念
    • Service
    • Binder机制
      • Binder是什么?
    • aidl
  • 尝试使用
  • 具体实现
    • 服务端
    • 客户端


必须看!!!,要不回头发现文章没啥用请别骂!!

提示1:首先介绍作者编写本文时的水平和状态(避免浪费大佬时间),如果想要直接快速了解如何使用,直接看尝试使用那一章即可。
提示2:由于一开始想将原理各方面都讲的很全面,但是最后由于时间不太够了,所以原理方面我只列了几篇我在学习时看到的写的比较好的参考文章,有需要的朋友可以去阅读一下。

  1. 毕业生初入职,公司项目主要是基于Android的跨平台设备,举个例子:小爱同学、需要使用一些摄像头或者其他外设的智能设备之类的。
  2. 大学时期没有学习过android,主要学习的内容为java web上的一些开发
  3. 入职后,我向前辈请教,前辈和我说去学习一下idle Service相关内容,于是便产生了本篇博客,用于记录自己的学习过程,如有理解错误或者表达错误的地方,欢迎给出指正或者建议。
  4. 我会从头记录自己的思考过程,以及学习流程,如有想要学习某项技术的小伙伴,也可以参考我的方法。

概念

 首先了解到安卓应用程序的四个常用组件,然后在这里见到了service这一关键词。
了解方式为 菜鸟教程

Service

  Service是android 系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互。service可以在很多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务总是藏在后台的。
 在网上搜索之后,了解到的一般都是service的运行流程、方式之类的具体场景使用方法,在这里就先不详细研究,我就大致了解了基础的概念。

Binder机制

 在了解学习aidl之前,需要先了解Binder机制。

Binder是什么?

  1. 机制:Binder是一种进程间通信的机制

  2. 驱动:Binder是一个虚拟物理设备驱动

  3. 应用层:Binder是一个能发起进程间通信的JAVA类

  4. Binder就是Android中的血管,在Android中我们使用Activity,Service等组件都需要和AMS(system_server)进行通信,这种跨进程的通信都是通过Binder完成。

  5. Activity,Service等组件和AMS不是同一个进程,其实也是多进程通信。
    tips1:具体可以参考以下链接,讲解的十分详细且清晰,不仅是概念介绍,还包括了原理级别的讲解,想要读懂需要对操作系统这门计算机基础课程有一定的了解。
    tips2:可以详细看一下传统的IPC方式和Binder中的IPC方式

参考链接:https://blog.csdn.net/ly0724ok/article/details/117566381/

aidl

 AIDL(Android 接口定义语言),可以使用它定义客户端与服务端进程间通信(IPC)的编程接口,在 Android 中,进程之间无法共享内存(用户空间),不同进程之间的通信一般使用 AIDL 来处理。
 序列化和反序列化:由于不同的进程有着不同的内存区域,并且它们只能访问自己的那一块内存区域,所以我们不能像平时那样,传一个句柄过去就完事了——句柄指向的是一个内存区域,现在目标进程根本不能访问源进程的内存,那把它传过去又有什么用呢?所以我们必须将要传输的数据转化为能够在内存之间流通的形式。这个转化的过程就叫做序列化与反序列化。
参考链接:aidl看这一篇就够了!

备注:该文章写的也很好


尝试使用

  在了解了一些内容后,我想要去尝试一下对aidl进行一个简单的应用,通过一个demo来进行说明,然后这个demo主要就是实现了客户端调动服务端的service,完成一个加法操作。

 在尝试使用的过程中出现了很多问题,我也耗费了很长时间才把这一个小小的,简单的demo给弄出来,显然是自己基础太差导致的问题,但是解决方案只要想找的话,肯定也是能够找到的。
以下是我在进行尝试使用时所参考的文章:
链接:

  1. Android:学习AIDL,这一篇文章就够了(上)
  2. 知识点-----AIDL(一)简单的aidl实现

 本次尝试分为服务端和客户端,服务端用于提供某一服务,然后客户端可以直接调用服务端创建的服务即可。
以下是使用步骤的目录,可以先大致了解下流程。

 服务端:

  1. 书写一个布局文件,用于显示页面
  2. 书写aidl文件记得rebuild项目
  3. 书写service文件+注册服务
  4. 书写服务端文件

 客户端:

  1. 书写aidl文件
  2. 书写客户端文件,并调用服务端服务

具体实现

服务端

  1. 书写布局文件(activity_main.xml)




<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    >

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加法器服务端"/>
    <EditText
        android:id="@+id/et_add_x"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <EditText
        android:id="@+id/et_add_y"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="add"/>







    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="相加结果为:"
            />
        <TextView
            android:id="@+id/tv_result"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

    LinearLayout>



LinearLayout>
  1. aidl文件(IAddAidlLnterface.aidl)
// IAddAidlLnterface.aidl
package com.example.myapplication;

// Declare any non-default types here with import statements

interface IAddAidlLnterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    int add(in int x, in int y);
}

== 编写完此代码后,需要clean project或者rebuild项目==

  1. 加法服务(AddService.java)
package com.example.myapplication;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class AddService extends Service {


    public AddService() {
    }



    IAddAidlLnterface.Stub mBinder = new IAddAidlLnterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public int add(int x, int y) throws RemoteException {
            return x + y;
        }
    };
    @Override
    public IBinder onBind(Intent intent) {
//        // TODO: Return the communication channel to the service.
//        throw new UnsupportedOperationException("Not yet implemented");
        Log.d("ning","调用了AddService.onBind");
        return mBinder;

    }
}

这里需要在AndroidManifest.xml中注册服务(AndroidManifest.xml)


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.myapplication">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">


        <service
            android:name=".AddService"
            android:enabled="true"
            android:exported="true">

            <intent-filter>
                <action android:name="com.example.add"/>
                <category android:name="android.intent.category.DEFAULT"/>
            intent-filter>

        service>

        <activity
            android:name=".ActFinishActivity"
            android:exported="false" />
        <activity
            android:name=".ActStartActivity"
            android:exported="false" />
        <activity
            android:name=".CalculatorActivity"
            android:exported="false" /> 
        <activity android:name=".MainActivity2" /> 
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>
    application>

manifest>
  1. 服务端代码(MainActivity.java)
package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private static final String Tag = "ning";
    private IAddAidlLnterface mService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //app启动后首先显示的布局,R是系统自动生成的类
        setContentView(R.layout.activity_main);
        TextView tv = findViewById(R.id.tv);
        tv.setText("服务端加法器");

//        //添加点击时间,跳转到MainActivity2
//        Button button = findViewById(R.id.button);
//        button.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View view) {
//                //意图对象
//                Intent intent = new Intent();
//                //编辑意图上下文
//                intent.setClass(MainActivity.this, ActStartActivity.class);
//                startActivity(intent);
//            }
//        });


        //学习activity生命周期
        //打印当前所处周期
        Log.d(Tag, "MainActivity onCreate");


        //实现aidl服务端
        aboutService();
        findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int x = Integer.parseInt(((EditText) findViewById(R.id.et_add_x)).getText().toString());
                int y = Integer.parseInt(((EditText) findViewById(R.id.et_add_y)).getText().toString());
                try {
                    Log.d("ning", "服务端 相加结果:" + mService.add(x, y));
                    TextView tv = (TextView) findViewById(R.id.tv_result);
                    int num = mService.add(x, y);
                    tv.setText(num + "");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

            }
        });
    }
    ServiceConnection mConn = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("ning", "服务端:连接 Service 成功");
            mService = IAddAidlLnterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private void aboutService() {
        Intent intent = new Intent(this, AddService.class);
        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
    }



    @Override
    protected void onStart() {
        super.onStart();
        //打印当前所处周期
        Log.d(Tag,"MainActivity onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        //打印当前所处周期
        Log.d(Tag,"MainActivity onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        //打印当前所处周期
        Log.d(Tag,"MainActivity onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        //打印当前所处周期
        Log.d(Tag,"MainActivity onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //打印当前所处周期
        Log.d(Tag,"MainActivity onDestroy");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        //打印当前所处周期
        Log.d(Tag,"MainActivity onRestart");
    }
}

541813460548. 运行结果
Android aidl 简单小demo学习过程记录(菜鸟详细版,快速上手aidl)_第1张图片

客户端

  1. 书写布局文件(activity_main.xml),这里基本上和服务端相似




<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    >

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加法器客户端"/>
    <EditText>
        android:id="@+id/et_add_x"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <EditText
        android:id="@+id/et_add_y"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="add"/>







    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="相加结果为:"
            />
        <TextView
            android:id="@+id/tv_result"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

    LinearLayout>



LinearLayout>
  1. aidl文件(IAddAidlLnterface.aidl)
    特别注意:
    这里需要创建一个和服务端相同的包来存放aidl文件,客户端文件目录如下
    Android aidl 简单小demo学习过程记录(菜鸟详细版,快速上手aidl)_第2张图片
    服务端代码如下:
// IAddAidlLnterface.aidl
package com.example.myapplication;

// Declare any non-default types here with import statements

interface IAddAidlLnterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    int add(in int x, in int y);
}

注:编写完此代码后,需要clean project或者rebuild项目
3. 客户端代码(MainActivity.java)

package com.example.demoaidlservice;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import com.example.myapplication.IAddAidlLnterface;

public class MainActivity extends AppCompatActivity {
    private IAddAidlLnterface mService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        aboutService();
        findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int x = Integer.parseInt(((EditText) findViewById(R.id.et_add_x)).getText().toString());
                int y = Integer.parseInt(((EditText) findViewById(R.id.et_add_y)).getText().toString());
                try {
                    Log.d("ning", "调用服务--客户端 相加结果:" + mService.add(x, y));
                    TextView tv = (TextView) findViewById(R.id.tv_result);
                    int num = x + y;
                    tv.setText(num + "");
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d("ning",e.toString());
                }
            }
        });
    }

    private void aboutService() {
        Intent intent = new Intent();
//        intent.setAction()
        intent.setClassName("com.example.myapplication","com.example.myapplication.AddService");
        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
        Log.d("ning", "aboutService成功");
    }


    ServiceConnection mConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            try {
                mService = IAddAidlLnterface.Stub.asInterface(service);
                Log.d("ning", "客户端:连接 Service 成功");
            }catch (Exception e){
                Log.d("ning", "客户端:连接 Service 失败");
            }


        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };


    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mConn);
    }



}
  1. 运行结果
    Android aidl 简单小demo学习过程记录(菜鸟详细版,快速上手aidl)_第3张图片

注:如果运行出现错误,可能是由于客户端代码中建立连接的部分写错了,我当初就是在这个位置出现了问题,我参考的别的博客中,不是使用这种方式来建立intent,导致我一直无法顺利调用服务端的service,如果读者出现类似问题了,可以往这里思考一下。
Android aidl 简单小demo学习过程记录(菜鸟详细版,快速上手aidl)_第4张图片

你可能感兴趣的:(android学习,android,学习,android,studio)