如何实现Android不同包类数据传输,Unity插件传值到主包并解决广播空指针
错误根因
你不能通过new BroadcastSender()的方式创建Activity实例,安卓的Activity是系统管理的组件,手动new出来的实例没有绑定系统上下文Context,调用需要Context的sendBroadcast方法时就会触发空指针异常。你最初用Intent.ACTION_SEND的方案也不对,这个Action是用来调用系统分享功能的,不适合同应用内跨模块传值。
修复方案(广播实现)
步骤1:修改MyPlugin类,移除手动创建Activity的逻辑,改为持有外部传入的Context
不需要单独的BroadcastSender类,直接在MyPlugin里处理广播发送逻辑即可:
package com.example.unity; import android.content.Context; import android.content.Intent; import android.util.Log; public class MyPlugin { private static final MyPlugin ourInstance = new MyPlugin(); private static final String LOGTAG = "AltGras"; private Context hostContext; public float surfaceArea ; public static MyPlugin getInstance() { return ourInstance; } private MyPlugin() { Log.i(LOGTAG, "Created MyPlugin"); } // 新增初始化方法,传入宿主上下文 public void init(Context context) { // 用Application级Context避免内存泄漏 this.hostContext = context.getApplicationContext(); } public void printText(float num) { surfaceArea = num; Log.d(LOGTAG, "printText: Text from Unity: "+num); // 直接发送自定义广播 Intent intent = new Intent(); intent.setAction("com.alternativegrass.alternativegrassapp.CUSTOM_SENDDATA_INTENT"); intent.putExtra("com.alternativegrass.alternativegrassapp.EXTRA_SURFACEAREA", num); hostContext.sendBroadcast(intent); } }
步骤2:在主包初始化MyPlugin
首先确保app模块的build.gradle中已经添加了对unityLibrary模块的依赖,之后在启动Unity的主Activity的onCreate方法中初始化MyPlugin:
// com.company.package1包下的主Activity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ...其他初始化逻辑 MyPlugin.getInstance().init(this); }
步骤3:在主包需要接收数据的类中注册广播接收器
比如要接收值的Activity中注册接收器:
private BroadcastReceiver dataReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { float surfaceArea = intent.getFloatExtra("com.alternativegrass.alternativegrassapp.EXTRA_SURFACEAREA", 0f); // 此处处理拿到的float值即可 Log.d("ReceiveUnityData", "拿到的值为:" + surfaceArea); } }; @Override protected void onStart() { super.onStart(); // 注册接收器,监听自定义广播Action IntentFilter filter = new IntentFilter("com.alternativegrass.alternativegrassapp.CUSTOM_SENDDATA_INTENT"); registerReceiver(dataReceiver, filter); } @Override protected void onStop() { super.onStop(); // 页面销毁时注销接收器,避免内存泄漏 unregisterReceiver(dataReceiver); }
可选更高效方案:接口回调
同应用内跨模块传值更推荐用接口回调,没有广播的通信开销,逻辑更直接:
- 在unityLibrary模块中定义回调接口:
package com.example.unity; public interface UnityDataCallback { void onReceiveSurfaceArea(float value); }
- MyPlugin中添加回调设置方法:
private UnityDataCallback callback; public void setDataCallback(UnityDataCallback callback) { this.callback = callback; } // printText方法修改为 public void printText(float num) { surfaceArea = num; if (callback != null) { callback.onReceiveSurfaceArea(num); } }
- 主包需要接收值的类直接实现接口设置即可:
MyPlugin.getInstance().setDataCallback(value -> { // 直接处理拿到的float值 });
内容的提问来源于stack exchange,提问作者Parms
相关产品推荐
相关产品推荐

