Update UI across processes through AIDL

Keywords: Android Java xml encoding

I. overview

This article will work with you to learn about AIDL implementation of cross process update UI.  
The requirement is: there are two activities in the same application, MainActivity and TempActivity, which are not in the same process.

Now we need to change the view in MainActivity through TempActivity, that is, to modify the display content of TextView in MainActivity and add two buttons, that is, to realize the function of updating UI across processes.

We can use AIDL or BroadcastReceiver to update the UI across processes. This article mainly uses AIDL. If you want to use AIDL
If you are not familiar with this article, please read it first:

2, Realization effect picture

Click the "jump to new process ACTIVITY" button in MainActivity to start the TempActivity of a new process. We first click the "binding service", so we start the service, and then click the "AIDL update" button to call the handler to realize the cross process update UI. Click back, we find that the TextView content in MainActivity page has been updated, and Two new buttons have been added.  

3, Core code

IViewManager.aidl 
There are two methods: one is to update the contents of TextView according to id, the other is to add view according to id

// IViewManager.aidl
package com.czhappy.remoteviewdemo;

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

interface IViewManager {
    void setTextViewText(in int id,in String text);//Set up TextView Content
    void addView(in int layoutId);                 //Add to View view
}

rebuild project allows IDE tools to generate java files corresponding to AIDL interface.

ViewAIDLService.java

package com.czhappy.remoteviewdemo.service;

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

import com.czhappy.remoteviewdemo.IViewManager;
import com.czhappy.remoteviewdemo.activity.MainActivity;

public class ViewAIDLService extends Service {
    private static final String TAG = "ViewAIDLService";
    private Binder viewManager = new IViewManager.Stub(){
        @Override
        public void setTextViewText(int id, String text) throws RemoteException {
            Message message = new Message();
            message.what = 2;
            Bundle bundle = new Bundle();
            bundle.putInt("id",id);
            bundle.putString("text",text);
            message.setData(bundle);
            new MainActivity.MyHandler(ViewAIDLService.this,getMainLooper()).sendMessage(message);
        }

        @Override
        public void addView(int layoutId) throws RemoteException {
            Message message = new Message();
            message.what = 3;
            Bundle bundle = new Bundle();
            bundle.putInt("layoutId",layoutId);
            message.setData(bundle);
            Log.i(TAG,"thread name = "+Thread.currentThread().getName());
            new MainActivity.MyHandler(ViewAIDLService.this,getMainLooper()).sendMessage(message);
        }

    };
    public ViewAIDLService() {
    }

    /**
     * Called when the client is bound to the service
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        return viewManager;
    }
}

MainActivity.java

package com.czhappy.remoteviewdemo.activity;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.TextView;

import com.czhappy.remoteviewdemo.R;

import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity {

    private static String TAG = "MainActivity";
    private static LinearLayout mLinearLayout;

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

        mLinearLayout = (LinearLayout) this.findViewById(R.id.mylayout);
    }

    public static class MyHandler extends Handler {
        WeakReference<Context> weakReference;
        public MyHandler(Context context, Looper looper) {
            super(looper);
            weakReference = new WeakReference<>(context);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.i(TAG, "handleMessage");
            switch (msg.what) {
                case 2: //modify MainActivity in TextView Content
                    Bundle bundle = msg.getData();
                    TextView textView = (TextView) mLinearLayout.findViewById(bundle.getInt("id"));
                    textView.setText(bundle.getString("text"));
                    break;
                case 3: //stay MainActivity Add in View view
                    LayoutInflater inflater = LayoutInflater.from(weakReference.get());
                    View view = inflater.inflate(msg.getData().getInt("layoutId"),null);
                    mLinearLayout.addView(view);
                default:
                    break;
            }
        }

    };

    public void readyGo(View view){
        Intent intent = new Intent(MainActivity.this, TempActivity.class);
        startActivity(intent);
    }

}

TempActivity.java

package com.czhappy.remoteviewdemo.activity;

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.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import com.czhappy.remoteviewdemo.IViewManager;
import com.czhappy.remoteviewdemo.R;
import com.czhappy.remoteviewdemo.service.ViewAIDLService;

public class TempActivity extends AppCompatActivity {

    private String TAG = "TempActivity";

    private IViewManager viewsManager;
    private boolean isBind = false;


    private ServiceConnection viewServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG,"onServiceConnected");
            viewsManager = IViewManager.Stub.asInterface(service);

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //recovery
            viewsManager = null;
        }
    };

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

    /**
     * Binding service
     */
    public void bindService(View view) {
        Intent viewServiceIntent = new Intent(this,ViewAIDLService.class);
        isBind = bindService(viewServiceIntent,viewServiceConnection, Context.BIND_AUTO_CREATE);
    }

    /**
     * Update UI
     */
    public void UpdateUI(View view){
        try {
            viewsManager.setTextViewText(R.id.mytext,"adopt AIDL Cross process modification TextView content");
            viewsManager.addView(R.layout.button_layout);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(isBind){
            unbindService(viewServiceConnection);
            isBind = false;
        }

    }

}

Configuration file Android manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.czhappy.remoteviewdemo">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".activity.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".activity.TempActivity"
            android:process=":remote">
        </activity>

        <service android:name="com.czhappy.remoteviewdemo.service.ViewAIDLService"/>

    </application>

</manifest>

Posted by pluginbaby on Sun, 05 Apr 2020 22:39:29 -0700