Py4J对接DJI Android MSDK报错及相关技术问题咨询
我正尝试在DJI无人机上集成YOLOv8(及更多机器学习功能),该无人机仅支持DJI Android MSDK,但我更熟悉Python,因此决定用Py4J创建网关服务器启动JVM,计划在Python端运行YOLO代码,Java端执行无人机指令。但DJI MSDK为Android开发环境构建,需在AndroidManifest文件中填写SDK密钥才能使用API。由于不在Android环境中,我调用setAppKey()方法并从Python端触发,却出现如下错误:
raise Py4JJavaError( py4j.protocol.Py4JJavaError: An error occurred while calling t.sdkSetUp. : java.lang.VerifyError: Constructor must call super() or this() before return Exception Details: Location: dji/sdk/sdkmanager/DJISDKManager.<init>()V @0: return Reason: Error exists in the bytecode Bytecode: 0000000: b12a 5959 5c5c 5c5c 5c5c 5c5c 5c5c b700 0000010: ff03 b501 0101 b501 03bb 0105 5903 b701 0000020: 08b5 010a b801 0ebe 0464 b501 1003 b501 0000030: 12bb 0056 59b8 0117 bb00 2859 2ab7 011a 0000040: b701 1db5 011f 01b5 0121 bb01 2359 b701 0000050: 24b5 0126 01b5 0128 01b5 012a 01b5 012c 0000060: 01b5 012e 01b5 0130 01b5 0132 01b5 0134 0000070: 01b5 0136 bb00 2259 2ab7 0137 b501 39bb 0000080: 0020 592a b701 3ab5 013c bb01 3e59 03b7 0000090: 0141 b501 43bb 0016 592a b701 44b5 0146 00000a0: bb00 1459 2ab7 0147 b501 49bb 0012 592a 00000b0: b701 4ab5 014c b801 51b8 0154 57a7 0034 00000c0: 4bb2 0156 592a b801 5c03 bd00 04b8 0162 00000d0: bb01 6459 b701 6513 0167 b800 ebb6 016b 00000e0: 2ab6 016f b601 6bb6 0172 03bd 0004 b801 00000f0: 62b1 Exception Handler Table: bci [182, 188] => handler: 192 Stackmap Table: full_frame(@192,{},{Object[#254]}) same_frame(@241) at org.example.Main.sdkSetUp(Main.java:19) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244) at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357) at py4j.Gateway.invoke(Gateway.java:282) at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132) at py4j.commands.CallCommand.execute(CallCommand.java:79) at py4j.GatewayConnection.run(GatewayConnection.java:238) at java.base/java.lang.Thread.run(Thread.java:831)
Python端代码
from py4j.java_gateway import JavaGateway gateway = JavaGateway() addition_app = gateway.entry_point addition_app.sdkSetUp() print("DJI sdk set up success!")
Java端代码
package org.example; import py4j.GatewayServer; import dji.sdk.sdkmanager.*; public class Main { public static void main(String[] args) { Main app = new Main(); GatewayServer server = new GatewayServer(app); server.start(); System.out.println("Gateway Server Started"); } public void sdkSetUp(){ DJISDKManager.setAppKey("some-hashed-sdk-key-generated-from-website"); } }
网关服务器可正常启动,但调用sdkSetUp函数时出现上述错误。我有以下几个问题,若能解答其一,我将不胜感激:
- DJI Android MSDK能否在常规Java环境而非Android环境中使用?
- setAppKey()是否与在AndroidManifest文件中修改SDK密钥作用相同?
- 针对我的项目需求,是否有更简便的方案实现绕开Android环境在DJI无人机上运行YOLO?
我还尝试创建模拟Android Context类和资源类作为DJI MSDK中registerApp()的输入,但需要导入Android核心库,且无法找到对应Android包。
问题解答
1. DJI Android MSDK能否在常规Java环境而非Android环境中使用?
不能。DJI Android MSDK是专为Android平台构建的,依赖大量Android系统核心API(如Context、Activity、系统服务等),其字节码针对Android Runtime(ART)优化,与标准JVM的字节码验证规则不兼容。你遇到的java.lang.VerifyError就是因为SDK类构造函数未遵循标准JVM的字节码要求——返回前未调用super()或this(),这在ART中可能被允许,但标准JVM会直接抛出验证错误。
2. setAppKey()是否与在AndroidManifest文件中修改SDK密钥作用相同?
效果类似但使用场景不同。Android环境下官方推荐通过AndroidManifest.xml的<meta-data>标签配置AppKey,SDK会自动读取;setAppKey()是特殊场景下手动设置密钥的API,但它仍需在Android环境中调用,因为后续SDK初始化流程依赖Android上下文环境,单独调用无法完成完整初始化。
3. 针对我的项目需求,是否有更简便的方案实现绕开Android环境在DJI无人机上运行YOLO?
有三种可行方案:
- 使用DJI Onboard SDK(OSDK):若无人机支持OSDK(如M300 RTK、M200系列),OSDK提供C++/Python接口,可直接在机载计算机(如Manifold 2)上运行,无需依赖Android环境,能直接用Python控制无人机并运行YOLOv8推理,架构更简洁。
- Android端+Python交互:若只能用Android MSDK,可在Android设备(遥控器或机载平板)开发简单应用调用MSDK控制无人机,通过Socket或HTTP与运行YOLO的Python程序通信——Python可在同一设备后台或局域网电脑上运行,传递图像数据与指令。
- 第三方Python封装:部分社区提供DJI Android MSDK的Python封装(基于JNI技术),但无官方维护,兼容性与稳定性需自行测试。
内容的提问来源于stack exchange,提问作者user22891151

