uni-app jump to Android native interface (Activity), and pass value interaction

Students who are in a hurry can just read this code, and don't read the rest:

var main = plus.android.runtimeMainActivity();  
var Intent= plus.android.importClass("android.content.Intent")  
intent.setComponent(new ComponentName("应用包名","应用包名.activity类名"));  
intent.putExtra("type", 1);  
main.startActivityForResult(intent, 0); 

 


1. Uni-app jumps to Android native interface (Activity) and transfers values

  • Front-end value transfer operation
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
</head>
<body>
<input type="button" value="js start native Activity" onclick="jsCallNativeActivity()"/>
</body>
<script type="text/javascript">
  function jsCallNativeActivity(){
  //获取宿主上下文
  var main = plus.android.runtimeMainActivity();
   //通过反射获取Android的Intent对象
  var Intent = plus.android.importClass("android.content.Intent");
  //通过宿主上下文创建 intent
  var intent = new Intent(main.getIntent());
  //设置要开启的Activity包类路径  com.HBuilder.integrate.MainActivity换掉你自己的界面
  intent.setClassName(main, "com.HBuilder.integrate.MainActivity");
  //开启新的任务栈 (跨进程)
  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  //向原生界面传值操作
  intent.putExtra("uni_key","来自uniapp的值");
  //开启新的界面
  main.startActivity(intent);
  }


</script>
</html>

Everyone who is doing Android knows that intent.putExtra (key, value) is to pass value operations between different components through Intent. For front-end developers, I suggest directly encapsulating it into json to pass the value, intent.putExtra("uni_json_key","{key," value1”}");

  • The Android side receives the value
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent mIntent = getIntent();
        if (mIntent!=null){
            //获取Intent,通过key获取对应的值
            String uniValue = mIntent.getStringExtra("uni_key");
            Toast.makeText(this, "uniValue="+uniValue, Toast.LENGTH_SHORT).show();
        }
    }
}

The effect is as follows:
Insert picture description here


2. Uni-app jumps to the Android native interface (Activity) and passes the value, and returns the uni-app with the return value


  • uni-app opens the android native interface and requests the return value
  function jsCallNativeActivity(){
  //获取宿主上下文
  var main = plus.android.runtimeMainActivity();
   //通过反射获取Android的Intent对象
  var Intent = plus.android.importClass("android.content.Intent");
  //通过宿主上下文创建 intent
  var intent = new Intent(main.getIntent());
  //设置要开启的Activity包类路径  com.HBuilder.integrate.MainActivity换掉你自己的界面
  intent.setClassName(main, "com.HBuilder.integrate.MainActivity");
  //开启新的任务栈 (跨进程)
  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  //uni向android原生界面传值
  intent.putExtra("uni_key","来自uniapp的值");

  //请求码保证了,开始的新界面和返回的是同一个操作
  var CODE_REQUEST=1000
  //采用startActivityForResult开启新的界面,当界面关闭时可以处理返回结果, CODE_REQUEST请求码是唯一标识
  main.startActivityForResult(intent,CODE_REQUEST);

  //设置原生界面返回后的回调操作
  main.onActivityResult = function(requestCode, resultCode, data) {
                if (requestCode == CODE_REQUEST) {
                  alert(requestCode); //这个是正确的 1000  
                  alert(resultCode);  //始终都是0  
                  alert(data);  //弹出 undefined   
                }
      }
  }
  • Click the button on the Android side to close the native interface and return the value
  public void backValue(View view) {
        Intent mIntent = new Intent();
        mIntent.putExtra("Native_RESULT_Key", "来自原生界面的返回值");
        setResult(Activity.RESULT_OK, mIntent);
        finish();
    }

After the above operation, theoretically it should be possible to return a value, but in fact, except for the requestCode which is correct, the other values ​​are all wrong. Why? I followed the official demo source code on Android and found that there was a bug. The onActivityResult method was actually called when the new interface was opened, and setResult(Activity.RESULT_OK, mIntent) when returning, and then onActivityResult did not leave at all, so In this way, resultCode and data are not assigned normally. As shown in the log below,
Insert picture description here
you can see that the official dug a hole here. How many people jumped into it. Why is his life cycle method called messy? The uni-app demo is written like this, using a proxy class to handle all event operations

Insert picture description here
You can only look at the official source code of Android,
Insert picture description here
that is, when we start the native activity and restart the interaction, onActivityResult will be called before onResume() to return the value of the previous interface. Now onActivityResult is not executed, indicating that uni-app is doing something in some places. The method is intercepted, resulting in an exception in the Android life cycle method callback; so this problem needs to be handled by uni-app to straighten out the Android life cycle


My personal solution is to use EventBus to manually call onActivityResult in SDK_WebApp, as follows

1. App.gradle dependency implementation 'org.greenrobot:eventbus:3.0.0'
2. Create DataSynEvent

public class DataSynEvent {
    public int requestCode;
    public int resultCode;
    public Intent data;

    public DataSynEvent(int requestCode, int resultCode, Intent data) {
        this.requestCode = requestCode;
        this.resultCode = resultCode;
        this.data = data;
    }
}

3. Modify SDK_WebApp.java

public class SDK_WebApp extends Activity implements IActivityDelegate {

    private static final String TAG = "SDK_WebApp";
     ....

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
            ....
         //注册EventBus
        EventBus.getDefault().register(this);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
        mEntryProxy.onStop(this);
         //解绑EventBus
        EventBus.getDefault().unregister(this);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.d(TAG, "onActivityResult: " + data + ",requestCode=" + requestCode + ",resultCode=" + resultCode);
        super.onActivityResult(requestCode, resultCode, data);
    if (data!=null){
    //第一次启动的时候调用这个方法data肯定为null.所以减少调用次数
            mEntryProxy.onActivityExecute(this, SysEventType.onActivityResult, new Object[]{requestCode, resultCode, data});
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onDataSynEvent(DataSynEvent event) {
        Log.d(TAG, "onDataSynEvent: ");
        //手动调用
        onActivityResult(event.requestCode, event.resultCode, event.data);
    }


}

4. Modify the return method of the native interface

 public void backValue(View view) {
        Intent data= new Intent();
        data.putExtra("Native_RESULT_Key", "来自原生界面的返回值");
        //用EventBus替换setResult(Activity.RESULT_OK,data);
        EventBus.getDefault().post(new DataSynEvent(1000,Activity.RESULT_OK,data));
        finish();
    }

5. Modify the front-end receiving method

  function jsCallNativeActivity(){
  //获取宿主上下文
  var main = plus.android.runtimeMainActivity();
   //通过反射获取Android的Intent对象
  var Intent = plus.android.importClass("android.content.Intent");
  //通过宿主上下文创建 intent
  var intent = new Intent(main.getIntent());
  //设置要开启的Activity包类路径  com.HBuilder.integrate.MainActivity换掉你自己的界面
  intent.setClassName(main, "com.HBuilder.integrate.MainActivity");
  //uni向android原生界面传值
  intent.putExtra("uni_key","来自uniapp的值");
     //开启新的任务栈 (跨进程)
  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  //请求码保证了,开始的新界面和返回的是同一个操作
  var CODE_REQUEST=1000
  //采用startActivityForResult开启新的界面,当界面关闭时可以处理返回结果, CODE_REQUEST请求码是唯一标识
  main.startActivityForResult(intent,CODE_REQUEST);
    //设置原生界面返回后的回调操作
    main.onActivityResult = function(requestCode, resultCode, data) {
                if (requestCode == CODE_REQUEST) {
                  alert(requestCode); //这个是正确的 1000
                  alert(resultCode);  //这个是正确的 -1
                  alert(data.getStringExtra("Native_RESULT_Key"));  //弹出 来自原生界面的返回值
                }
     }
  }

6. The effect of the above
Insert picture description here
* Seeing the official forum someone asked mainwhat it is, it is actually an instance object of the host Activity obtained through reflection, that is com.HBuilder.integrate.SDK_WebApp*


Supplement on May 12, 2020

Regarding communication, uni-app officially gave the relevant api host App to send events to the applet at the end of April 2020

  • Android platform API
DCUniMPSDK.getInstance().sendUniMPEvent(event, data)
  •  
  • Parameter Description
parameter Types of Required Description
event String yes Event that triggered the event
data String or JSON yes Parameters carried by the event
  • return value
Types of Description
boolean true indicates that the event notification is successful. false means failure. Can be viewed through log.

Guess you like

Origin blog.csdn.net/THMAIL/article/details/112278131