一、Remote
Remote(遠程的)是Android系統提供的一種跨進程通信(IPC)機制,允許一個應用程序(或進程)調用另一個進程中的服務或UI元素。通過Remote機制,應用程序可以像訪問本地服務或UI元素一樣訪問遠程服務或UI元素,這為Android應用程序開發提供了更多的靈活性。
二、Remotely
Android提供了兩種方式實現對Remote的遠程訪問,一種是通過AIDL(Android介面定義語言)生成Java介面的方式,另一種則是通過RemoteView實現。
三、Remote Control
RemoteView(遠程視圖)是一種特殊的View,使用它可以在一個進程中創建一個View,然後將該View在另一個進程中顯示。RemoteView在設計上基本和普通View一致,能夠支持大部分的View功能和屬性,但是有一定的限制,例如:
- 不支持自定義的繪製代碼 - 只支持一部分的View屬性,如:layout_width、layout_height、background、padding等屬性 - 只能訪問遠程進程中已經註冊的布局文件或View ID - 只能更新布局中已存在的View(即不能動態增加Views)
四、Remote軟體下載
在實際應用中,如果需要在一個應用程序中訪問另一個應用程序中的RemoteView,我們需要在另一個應用程序中註冊一個RemoteView布局文件或者View ID,並在需要顯示該View的時候,通過RemoteViews類構造遠程視圖,然後通過AppWidgetManager來更新該遠程視圖。下面是一個註冊RemoteView布局文件並展示的示例代碼:
// 在另一個進程中的RemoteService中註冊RemoteView布局 public class RemoteService extends Service { private static final int LAYOUT_ID = R.layout.remote_view_layout; @Override public IBinder onBind(Intent intent) { return new RemoteBinder(); } private class RemoteBinder extends IRemoteBinder.Stub() { @Override public RemoteViews getRemoteView() throws RemoteException { RemoteViews remoteViews = new RemoteViews(getApplicationContext().getPackageName(), LAYOUT_ID); // 設置點擊事件 Intent intent = new Intent(getApplicationContext(), RemoteActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0); remoteViews.setOnClickPendingIntent(R.id.button, pendingIntent); return remoteViews; } } } // 在本地應用程序中通過RemoteViews獲取遠程視圖並展示 public class LocalActivity extends Activity { private static final String PACKAGE_NAME = "com.example.remote"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AppWidgetManager manager = AppWidgetManager.getInstance(this); RemoteViews remoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remote_view_layout); ComponentName componentName = new ComponentName(PACKAGE_NAME, RemoteService.class.getName()); // 獲取另一個進程中RemoteService返回的RemoteViews remoteViews = manager.getAppWidgetOptions(componentName).getBoolean(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, false) ? manager.createWidget(this, R.xml.widget_gadget) : remoteViews; // 更新本地View ViewGroup viewGroup = findViewById(R.id.container); viewGroup.addView(remoteViews.apply(this, viewGroup)); } }
五、Remove
除了RemoteView,在使用AIDL調用Remote服務時,我們也可以在Binder中返回RemoteView,這樣就能在服務端創建一個View,然後在客戶端中展示。
// 服務端實現 public class RemoteService extends Service { @Override public IBinder onBind(Intent intent) { return new RemoteBinder(); } private class RemoteBinder extends IRemoteBinder.Stub() { @Override public RemoteViews getRemoteView() throws RemoteException { // 創建一個RemoteView並返回 RemoteViews remoteViews = new RemoteViews(getApplicationContext().getPackageName(), R.layout.remote_view_layout); return remoteViews; } @Override public IBinder getRemoteBinder() throws RemoteException { // 返回帶有遠程View的Binder return new RemoteViewBinder(new RemoteViews(getApplicationContext().getPackageName(), R.layout.remote_view_layout)); } } // 返回帶有遠程View的Binder private class RemoteViewBinder extends IRemoteBinder.Stub() { RemoteViews remoteViews; public RemoteViewBinder(RemoteViews remoteViews) { this.remoteViews = remoteViews; } @Override public RemoteViews getRemoteView() throws RemoteException { return remoteViews; } } } // 客戶端實現 public class LocalActivity extends Activity { IRemoteBinder remoteService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 綁定RemoteService服務 Intent intent = new Intent(this, RemoteService.class); bindService(intent, conn, Context.BIND_AUTO_CREATE); } private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { remoteService = IRemoteBinder.Stub.asInterface(service); try { // 獲取帶有遠程View的Binder IRemoteBinder remoteBinder = remoteService.getRemoteBinder(); // 展示遠程View RemoteViews remoteViews = remoteBinder.getRemoteView(); ViewGroup viewGroup = findViewById(R.id.container); viewGroup.addView(remoteViews.apply(getApplicationContext(), viewGroup)); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; }
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/291740.html