【Android】Service(java)

参考资料

  • https://blog.csdn.net/x2584179909/article/details/108319973
  • https://developer.android.google.cn/guide/components/bound-services?hl=zh-cn
  • https://gitee.com/18071569361/ApiDemos/tree/master
  • https://blog.csdn.net/hello_1995/article/details/122094512

代码

  • https://gitee.com/hellosunshine/service-android-java.git

内容

服务类型

  • 前台服务
  • 后台服务
  • 绑定服务

服务的回调方法

  • onStartCommand()
    当另一个组件请求启动服务时
  • onBind()
    绑定服务
  • onCreate()
    首次创建会调用
  • onDestroy()
    销毁服务

IntentService

  • 创建服务
package com.example.serviceandroidjava;

import android.app.IntentService;
import android.content.Intent;

import androidx.annotation.Nullable;

public class HelloIntentService extends IntentService {
   public HelloIntentService() {
       super("HelloIntentService");
   }

   @Override
   protected void onHandleIntent(@Nullable Intent intent) {
       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           Thread.currentThread().interrupt();
       }
   }
}

  • manifest.xml 注册服务
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   package="com.example.serviceandroidjava">

   <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.ServiceAndroidJava"
       tools:targetApi="31">
       <service
           android:name=".HelloIntentService"
           android:exported="false" />

       <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>

Service

package com.example.serviceandroidjava;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class HelloService extends Service {
    private Looper serviceLooper;
    private ServiceHandler serviceHandler;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            stopSelf(msg.arg1);
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("ServiceStartArgs",
                Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();
        serviceLooper = thread.getLooper();
        serviceHandler = new ServiceHandler(serviceLooper);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
        Message message = serviceHandler.obtainMessage();
        message.arg1 = startId;
        serviceHandler.sendMessage(message);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
    }
}

启动服务

        Intent intent = new Intent(this, HelloService.class);
        startService(intent);

绑定服务

binder方式
  • Binder
    实现自有的Binder类,让客户端通过该类直接访问服务中公共方法
  • 创建服务
package com.example.serviceandroidjava;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

import androidx.annotation.Nullable;

import java.util.Random;

public class LocalService extends Service {
    private final IBinder binder = new LocalBinder();
    private final Random mGenerator = new Random();

    ///返回LocalService实例,从而客户端可以调用服务中的公共方法
    public class LocalBinder extends Binder {
        LocalService getService() {
            return LocalService.this;
        }
    }

    //返回binder
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    ///公共方法
    public int getRandomNumber() {
        return mGenerator.nextInt(100);
    }
}

  • manifest注册服务
<service
            android:name=".LocalService"
            android:exported="false" />
  • 绑定服务\解绑服务\
package com.example.serviceandroidjava;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    LocalService mService;
    boolean mBound = false;
    private Button btn;

    @Override
    protected void onStart() {
        super.onStart();
        //绑定服务
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //解绑服务
        unbindService(connection);
        mBound = false;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //启动服务
//      Intent intent = new Intent(this, HelloService.class);
//      startService(intent);

        //启动前台服务
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//            Intent intent = new Intent(this, ForegroundService.class);
//            startService(intent);
//            Context context = getApplicationContext();
//            context.startForegroundService(intent);
//        } else {
//            Log.i("MainActivity", "版本问题");
//        }

        //点击获取随机数字(绑定服务)
        btn = findViewById(R.id.button);
        btn.setOnClickListener(view -> {
            if (mBound) {
                int number = mService.getRandomNumber();
                Toast.makeText(this, "number: " + number, Toast.LENGTH_LONG).show();
            } else {
                Log.i("MainActivity", "未绑定上");
            }
        });
    }

    private final ServiceConnection connection = new ServiceConnection() {
        //连接服务
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            LocalService.LocalBinder binder = (LocalService.LocalBinder) iBinder;
            mService = binder.getService();
            mBound = true;
        }

        //断开服务
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBound = false;
        }
    };
}
  • 运行,调用服务中的获取随机数字
    请添加图片描述
Messenger方式
  • 创建服务
package com.example.serviceandroidjava.bindServiceMessenger;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class MessengerService extends Service {
    static final int MSG_SAY_HELLO = 1;

    static class IncomingHandler extends Handler {
        private Context mContext;

        IncomingHandler(Context context) {
            mContext = context.getApplicationContext();
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(mContext, "hello!", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    Messenger messenger;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        Handler handler = new IncomingHandler(this);
        messenger = new Messenger(handler);
        return messenger.getBinder();
    }
}
  • 绑定服务/解绑服务/发送Message
package com.example.serviceandroidjava.bindServiceMessenger;

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.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;

import com.example.serviceandroidjava.R;

public class ActivityMessenger extends AppCompatActivity {
    Messenger messenger = null;
    boolean bound;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger);
        button = findViewById(R.id.sayHelloBtn);
        button.setOnClickListener(this::sayHello);
    }

    //绑定服务
    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    //解绑服务
    @Override
    protected void onStop() {
        super.onStop();
        if (bound) {
            unbindService(mConnection);
            bound = false;
        }
    }

    //发送Message
    private void sayHello(View view) {
        if (!bound)
            return;
        Message message = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        try {
            messenger.send(message);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            messenger = new Messenger(iBinder);
            bound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            messenger = null;
            bound = false;
        }
    };
}
ServiceConnection
private final ServiceConnection myServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //系统调用该方法以传递服务的onBind()方法所返回的IBinder
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            //当与服务连接意外中断时,例如服务崩溃或被终止时
            //取消绑定不会调用
        }
    };

管理绑定服务的生命周期

  • unbinderService() ->onUnbind()-> stopSelf()/stopService()->onDestory
  • unbinderService()->onUnbind()->bindService()->onBind()
  • unbinderService()->onUnbind()->bindService()->onRebind()
    请添加图片描述

前台运行服务&通知

  • 请求前台服务的权限
<!--前台服务-->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  • 创建服务并创建通知通道
package com.example.serviceandroidjava;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

public class ForegroundService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Intent notificationIntent = new Intent(this, MainActivity.class);
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent,
                    PendingIntent.FLAG_IMMUTABLE);
            String channelId = createNotification();
            Notification notification = new Notification.Builder(this, channelId)
                    .setContentTitle("通知标题")
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setTicker("serviceTicker")
                    .setContentText("通知内容")
                    .setContentIntent(pendingIntent)
                    .build();
            startForeground(1, notification);
        } else {
            Log.i("MainActivity", "版本问题");
        }
        return super.onStartCommand(intent, flags, startId);
    }

    //创建消息通道
    private String createNotification() {
        NotificationChannel notificationChannel = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            notificationChannel = new NotificationChannel("ForegroundService", "前台服务", NotificationManager.IMPORTANCE_DEFAULT);
            notificationChannel.setLightColor(Color.BLUE);
            notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(notificationChannel);
        }
        return "ForegroundService";
    }
}
  • manifest注册服务
        <service
            android:name=".ForegroundService"
            android:exported="false" />
  • 启动服务后再作为前台服务
//启动前台服务
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Intent intent = new Intent(this, ForegroundService.class);
            startService(intent);
            Context context = getApplicationContext();
            context.startForegroundService(intent);
        } else {
            Log.i("MainActivity", "版本问题");
        }
  • 运行MainActivity

请添加图片描述

  • 声明前台服务的类型
<service
           android:name=".ForegroundService"
           android:exported="false"
           android:foregroundServiceType="location|camera"/>
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
               startForeground(1, notification, FOREGROUND_SERVICE_TYPE_LOCATION | FOREGROUND_SERVICE_TYPE_CAMERA);
           } else {
               startForeground(1, notification);
           }

管理服务的生命周期

package com.example.serviceandroidjava;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import androidx.annotation.Nullable;

public class ExampleService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

调用顺序:onCreate->onStartCommand->(onBind->onUnbind->onRebind)->onDestory

AIDL(接口定义语言)

AIDL用处

需要不同应用的客户端通过IPC方式访问服务,并且希望在服务中进行多线程处理时,使用。利用它定义服务端与客户端均认可的编程接口,以便二者使用进程间通信(IPC)

  • 处理多线程
  • 多客户端并发访问(Messenger是单线程)
实现进程间通信(AIDL)
  • 创建两个Module(一个为Server,一个为Client)
    在这里插入图片描述
  • 创建AIDL文件(aidl文件须一致,包名也一致)
    在这里插入图片描述
    在这里插入图片描述
// IRemoteService.aidl
package com.example.server_aidl;

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

interface IRemoteService {
    /**
     * 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);
}
  • 创建AIDL后要rebuild,从而生成java文件
    在这里插入图片描述
  • 服务端创建服务
    在这里插入图片描述
    server中的manifest
    修改server标签,添加action
        <service
            android:name=".RemoteService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.aidl" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>
  • 完善RemoteService
package com.example.serveraidl;

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

import com.example.server_aidl.IRemoteService;

public class RemoteService extends Service {
    private final String TAG = "RemoteService";

    public RemoteService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate()");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind()");
        return binder;
    }

    private final IRemoteService.Stub binder = new IRemoteService.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
            Log.d(TAG, "basicTypes: anInt: " + anInt);
            Log.d(TAG, "basicTypes: aLong: " + aLong);
            Log.d(TAG, "basicTypes: aBoolean: " + aBoolean);
            Log.d(TAG, "basicTypes: aFloat: " + aFloat);
            Log.d(TAG, "basicTypes: aDouble: " + aDouble);
            Log.d(TAG, "basicTypes: aString: " + aString);
        }
    };
}

当客户端连接服务端时,若客户端调用basicTypes方法,则能看到输出日志

  • 配置客户端
    基本的绑定服务和解绑服务的流程
package com.example.clientaidl;

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 com.example.server_aidl.IRemoteService;

public class MainActivity extends AppCompatActivity {
    private final String TAG = "MainActivity";
    private IRemoteService iRemoteService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    //绑定服务
    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent();
        //对应注册服务的action
        intent.setAction("com.example.aidl");
        //对应服务端包名
        intent.setPackage("com.example.serveraidl");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    //解绑
    @Override
    protected void onStop() {
        super.onStop();
        unbindService(mConnection);
    }

    ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d(TAG, "onServiceConnected");
            //asInterface
            //该方法会接收 IBinder(通常是传递给客户端 onServiceConnected() 回调方法的参数),并返回 Stub 接口的实例。
            iRemoteService = IRemoteService.Stub.asInterface(iBinder);
            try {
                iRemoteService.basicTypes(0, 1, true, 2, 3, "文本");
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d(TAG, "onServiceDisconnected");
            iRemoteService = null;
        }
    };
}
  • 注意此处的Action和Package要对应
    在这里插入图片描述
  • 运行
    先运行Server,在运行Client,就看到日志输出了
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
AIDL传递对象
  • 服务端创建Rect.aidl文件,并指定路径
// Rect.aidl
package com.example.server_aidl;

parcelable Rect;
// IRemoteService.aidl
package com.example.server_aidl;
import com.example.server_aidl.Rect;
// Declare any non-default types here with import statements

interface IRemoteService {
    /**
     * 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);
    void addRectInOut(inout Rect rect);
}

在这里插入图片描述

  • 对应路径下创建Rect类,须一致
package com.example.server_aidl;

import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;

public class Rect implements Parcelable {
    private int left;
    private int top;
    private int right;
    private int bottom;

    public Rect(int left, int top, int right, int bottom) {
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }

    public static final Creator<Rect> CREATOR = new Creator<Rect>() {
        public Rect createFromParcel(Parcel in) {
            return new Rect(in);
        }

        public Rect[] newArray(int size) {
            return new Rect[size];
        }
    };

    private Rect(Parcel in) {
        readFromParcel(in);
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(left);
        out.writeInt(top);
        out.writeInt(right);
        out.writeInt(bottom);
    }

    public void readFromParcel(Parcel in) {
        left = in.readInt();
        top = in.readInt();
        right = in.readInt();
        bottom = in.readInt();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @NonNull
    @Override
    public String toString() {
        return "Rect[left:" + left + ",top:" + top + ",right:" + right + ",bottom:" + bottom + "]";
    }
}

在这里插入图片描述

  • 创建好了之后,rebuild一下,IRemoteService.java就会更新一个新的方法addRectInOut
    在这里插入图片描述
  • 客户端也一致,先创建Rect.aidl
// Rect.aidl
package com.example.server_aidl;

// Declare Rect so AIDL can find it and knows that it implements
// the parcelable protocol.
parcelable Rect;
  • 在IRemoteService.aidl中也引用Rect,并声明方法
// IRemoteService.aidl
package com.example.server_aidl;
import com.example.server_aidl.Rect;

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

interface IRemoteService {
    /**
     * 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);
    void addRectInOut(inout Rect rect);
}
  • 在同样的路径下创建Rect.java类
package com.example.server_aidl;

import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;

public class Rect implements Parcelable {
    private int left;
    private int top;
    private int right;
    private int bottom;

    public Rect(int left, int top, int right, int bottom) {
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }

    public static final Creator<Rect> CREATOR = new Creator<Rect>() {
        public Rect createFromParcel(Parcel in) {
            return new Rect(in);
        }

        public Rect[] newArray(int size) {
            return new Rect[size];
        }
    };

    private Rect(Parcel in) {
        readFromParcel(in);
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(left);
        out.writeInt(top);
        out.writeInt(right);
        out.writeInt(bottom);
    }

    public void readFromParcel(Parcel in) {
        left = in.readInt();
        top = in.readInt();
        right = in.readInt();
        bottom = in.readInt();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @NonNull
    @Override
    public String toString() {
        return "Rect[left:" + left + ",top:" + top + ",right:" + right + ",bottom:" + bottom + "]";
    }
}

在这里插入图片描述

  • rebuild之后,也会生成一个方法
    在这里插入图片描述
  • 修改服务端中的RemoteService.java,实现addRectInput,接受Rect对象,输出日志
package com.example.serveraidl;

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

import com.example.server_aidl.IRemoteService;
import com.example.server_aidl.Rect;

public class RemoteService extends Service {
    private final String TAG = "RemoteService";

    public RemoteService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate()");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind()");
        return binder;
    }

    private final IRemoteService.Stub binder = new IRemoteService.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
            Log.d(TAG, "basicTypes: anInt: " + anInt);
            Log.d(TAG, "basicTypes: aLong: " + aLong);
            Log.d(TAG, "basicTypes: aBoolean: " + aBoolean);
            Log.d(TAG, "basicTypes: aFloat: " + aFloat);
            Log.d(TAG, "basicTypes: aDouble: " + aDouble);
            Log.d(TAG, "basicTypes: aString: " + aString);
        }

        //实现addRectInOut,接受Rect对象
        @Override
        public void addRectInOut(Rect rect) throws RemoteException {
            Log.d(TAG, "addRectInOut:" + rect.toString());
        }
    };
}
  • 客户端调用服务的方法addRectInOut,传入Rect实例
package com.example.clientaidl;

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 com.example.server_aidl.IRemoteService;
import com.example.server_aidl.Rect;

public class MainActivity extends AppCompatActivity {
    private final String TAG = "MainActivity";
    private IRemoteService iRemoteService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    //绑定服务
    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent();
        //对应注册服务的action
        intent.setAction("com.example.aidl");
        //对应服务端包名
        intent.setPackage("com.example.serveraidl");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    //解绑
    @Override
    protected void onStop() {
        super.onStop();
        unbindService(mConnection);
    }

    ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.d(TAG, "onServiceConnected");
            //asInterface
            //该方法会接收 IBinder(通常是传递给客户端 onServiceConnected() 回调方法的参数),并返回 Stub 接口的实例。
            iRemoteService = IRemoteService.Stub.asInterface(iBinder);
            try {
                iRemoteService.basicTypes(0, 1, true, 2, 3, "文本");
                iRemoteService.addRectInOut(new Rect(1, 2, 3, 4));
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d(TAG, "onServiceDisconnected");
            iRemoteService = null;
        }
    };
}

在这里插入图片描述

  • 运行service和client(先service开启,后开启client),查看日志,技能看到接受了Rect对象
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sheng_er_sheng

打赏是什么?好吃么

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值