AIDL示例
-
服务端
-
aidl
IPlayerService.aidl
package com.example.aidl; import com.example.aidl.MusicInfo; import com.example.aidl.IMetadataUpdateCallback; interface IPlayerService { MusicInfo getMusicInfo(); void startPlay(); void endPlay(); void registerMetadataUpdateCallback(IMetadataUpdateCallback callback); void unregisterMetadataUpdateCallback(IMetadataUpdateCallback callback); }
MusicInfo.aidl
package com.example.aidl; parcelable MusicInfo;
IMetadataUpdateCallback.aidl
package com.example.aidl; import com.example.aidl.MusicInfo; interface IMetadataUpdateCallback { void onMetadataUpdate(in MusicInfo musicInfo); }
-
service
PlayerService.java
package com.example.aidl; import android.annotation.TargetApi; import android.app.Service; import android.content.Intent; import android.os.Build; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; /** * @author Dongping Wang * date 2022/7/14 0:12 */ public class PlayerService extends Service { private static final String TAG = "PlayerService"; private MusicInfo mMusicInfo = new MusicInfo("稻香", "周杰伦"); @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate"); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind"); return mBinder; } @Override public boolean onUnbind(Intent intent) { boolean b = super.onUnbind(intent); Log.d(TAG, "onUnbind"); return b; } @Override public void onRebind(Intent intent) { super.onRebind(intent); Log.d(TAG, "onRebind"); } private IBinder mBinder = new IPlayerService.Stub() { private RemoteCallbackList<IMetadataUpdateCallback> callbacks = new RemoteCallbackList<IMetadataUpdateCallback>() { @Override public void onCallbackDied(IMetadataUpdateCallback callback) { super.onCallbackDied(callback); Log.d(TAG, "onCallbackDied:" + callback); } }; @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) private void notifyMetadataUpdated() { callbacks.beginBroadcast(); for (int i = 0; i < callbacks.getRegisteredCallbackCount(); i++) { try { callbacks.getBroadcastItem(i).onMetadataUpdate(mMusicInfo); } catch (RemoteException e) { e.printStackTrace(); } } callbacks.finishBroadcast(); } @Override public MusicInfo getMusicInfo() throws RemoteException { Log.d(TAG, "getMusicInfo: " + mMusicInfo.toString()); return mMusicInfo; } @Override public void startPlay() throws RemoteException { Log.d(TAG, "startPlay"); // fixme:模拟当前歌曲变化,测试用 notifyMetadataUpdated(); } @Override public void endPlay() throws RemoteException { Log.d(TAG, "endPlay"); } @Override public void registerMetadataUpdateCallback(IMetadataUpdateCallback callback) throws RemoteException { Log.d(TAG, "registerMetadataUpdateCallback:" + callback); callbacks.register(callback); } @Override public void unregisterMetadataUpdateCallback(IMetadataUpdateCallback callback) throws RemoteException { Log.d(TAG, "unregisterMetadataUpdateCallback:" + callback); callbacks.unregister(callback); } }; }
服务在AndroidManifest中配置,指定:Remote进程
<service android:name=".PlayerService" android:enabled="true" android:exported="true" android:process=":Remote"> <intent-filter> <action android:name="example.intent.action.TEST_AIDL" /> </intent-filter> </service>
MusicInfo.java
package com.example.aidl; import android.os.Parcel; import android.os.Parcelable; /** * @author Dongping Wang * date 2022/7/14 0:18 */ public class MusicInfo implements Parcelable { private String title; private String singer; public MusicInfo() { } public MusicInfo(String title, String singer) { this.title = title; this.singer = singer; } protected MusicInfo(Parcel in) { title = in.readString(); singer = in.readString(); } public static final Creator<MusicInfo> CREATOR = new Creator<MusicInfo>() { @Override public MusicInfo createFromParcel(Parcel in) { return new MusicInfo(in); } @Override public MusicInfo[] newArray(int size) { return new MusicInfo[size]; } }; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getSinger() { return singer; } public void setSinger(String singer) { this.singer = singer; } @Override public String toString() { return "MusicInfo{" + "title='" + title + '\'' + ", singer='" + singer + '\'' + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(title); dest.writeString(singer); } }
-
-
客户端
通过PlayerServiceManager 进行调用服务端代码
package com.example.aidl; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** * @author Dongping Wang * date 2022/7/14 22:04 */ public final class PlayerServiceManager { private static final String ACTION_PLAYER_SERVICE = "example.intent.action.TEST_AIDL"; private static final String PACKAGE_PLAYER_SERVICE = "com.example.aidl"; private static final String TAG = "PlayerServiceManager"; private Context mContext; private ServiceConnection mServiceConn; private volatile boolean mServiceRegistered; private IPlayerService playerService; private List<PlayerServiceConnectionListener> listeners = new CopyOnWriteArrayList<>(); public static PlayerServiceManager newInstance(Context context) { return new PlayerServiceManager(context); } private PlayerServiceManager(Context context) { this.mContext = context; } public boolean bindService() { if (mServiceRegistered) { return true; } mServiceConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, final IBinder service) { Log.d(TAG, "onServiceConnected"); playerService = IPlayerService.Stub.asInterface(service); for (PlayerServiceConnectionListener listener : listeners) { listener.onServiceConnected(); } try { service.linkToDeath(new IBinder.DeathRecipient() { @Override public void binderDied() { Log.d(TAG, "binderDied"); service.unlinkToDeath(this, 0); bindService(); } }, 0); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "onServiceDisconnected"); for (PlayerServiceConnectionListener listener : listeners) { listener.onServiceDisconnected(); } playerService = null; } }; Intent intent = new Intent().setAction(ACTION_PLAYER_SERVICE).setPackage(PACKAGE_PLAYER_SERVICE); mServiceRegistered = mContext.bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE); return mServiceRegistered; } public boolean unbindService() { if (!mServiceRegistered) { return false; } if (mServiceConn != null) { mContext.unbindService(mServiceConn); mServiceRegistered = false; return true; } return false; } public void startPlay() { if (playerService != null) { try { playerService.startPlay(); } catch (RemoteException e) { e.printStackTrace(); } } } public void endPlay() { if (playerService != null) { try { playerService.endPlay(); } catch (RemoteException e) { e.printStackTrace(); } } } public MusicInfo getMusicInfo() { if (playerService != null) { try { return playerService.getMusicInfo(); } catch (RemoteException e) { e.printStackTrace(); } } return null; } public void registerMetadataUpdateCallback(IMetadataUpdateCallback callback) { if (playerService != null) { try { playerService.registerMetadataUpdateCallback(callback); } catch (RemoteException e) { e.printStackTrace(); } } } public void unregisterMetadataUpdateCallback(IMetadataUpdateCallback callback) { if (playerService != null) { try { playerService.unregisterMetadataUpdateCallback(callback); } catch (RemoteException e) { e.printStackTrace(); } } } public void registerPlayerServiceConnectionListener(PlayerServiceConnectionListener listener) { if (!listeners.contains(listener)) { listeners.add(listener); } } public void unregisterPlayerServiceConnectionListener(PlayerServiceConnectionListener listener) { if (listeners.contains(listener)) { listeners.remove(listener); } } public interface PlayerServiceConnectionListener { void onServiceConnected(); void onServiceDisconnected(); } }
MainActivity中四个按按钮来绑定、解绑、调用
package com.example.aidl; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; import android.view.View; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private PlayerServiceManager playerService = PlayerServiceManager.newInstance(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void bindService(View view) { playerService.bindService(); playerService.registerPlayerServiceConnectionListener(listener); } public void unbindService(View view) { playerService.unregisterMetadataUpdateCallback(callback); playerService.unbindService(); } public void startPlay(View view) { playerService.startPlay(); } public void endPlay(View view) { playerService.endPlay(); } private final IMetadataUpdateCallback callback = new IMetadataUpdateCallback.Stub() { @Override public void onMetadataUpdate(MusicInfo musicInfo) throws RemoteException { Log.d(TAG, "onMetadataUpdate:" + musicInfo.toString()); } }; private final PlayerServiceManager.PlayerServiceConnectionListener listener = new PlayerServiceManager.PlayerServiceConnectionListener() { @Override public void onServiceConnected() { playerService.registerMetadataUpdateCallback(callback); } @Override public void onServiceDisconnected() { } }; }
输出结果:
2022-07-16 12:44:42.100 1874-1903/system_process I/ActivityManager: Start proc 9341:com.example.aidl:Remote/u0a133 for service {com.example.aidl/com.example.aidl.PlayerService} 2022-07-16 12:44:42.266 9341-9341/? D/PlayerService: onCreate 2022-07-16 12:44:42.266 9341-9341/? D/PlayerService: onBind 2022-07-16 12:44:42.267 9307-9307/com.example.aidl D/PlayerServiceManager: onServiceConnected 2022-07-16 12:44:42.269 9341-9361/? D/PlayerService: registerMetadataUpdateCallback:com.example.aidl.IMetadataUpdateCallback$Stub$Proxy@4a38442 2022-07-16 12:44:44.959 9341-9361/? D/PlayerService: startPlay 2022-07-16 12:44:44.961 9307-9307/com.example.aidl D/MainActivity: onMetadataUpdate:MusicInfo{title='稻香', singer='周杰伦'} 2022-07-16 12:44:47.278 9341-9361/? D/PlayerService: unregisterMetadataUpdateCallback:com.example.aidl.IMetadataUpdateCallback$Stub$Proxy@e410990 2022-07-16 12:44:47.281 9341-9341/? D/PlayerService: onUnbind 2022-07-16 12:44:47.281 9341-9341/? D/PlayerService: onDestroy