【问题标题】:How can I get stack trace information on a device in CodenameOne?如何在 CodenameOne 中获取设备上的堆栈跟踪信息?
【发布时间】:2018-06-18 19:11:23
【问题描述】:

我的应用在模拟器中运行良好,在 Android 手机上运行良好,但在 Apple 手机上,我在启动过程中收到“ArrayIndexOutOfBounds:0”错误,没有任何解释。如何在堆栈跟踪处进行调试?

这是一个很好的开始(来自https://www.codenameone.com/blog/handling-the-exception.html

Display.getInstance().addEdtErrorHandler(new ActionListener() {
 public void actionPerformed(ActionEvent evt) {
    evt.consume();
    Log.p("Exception in AppName version " +Display.getInstance().getProperty("AppVersion", "Unknown"));
    Log.p("OS " + Display.getInstance().getPlatformName());
    Log.p("Error " + evt.getSource());
    Log.p("Current Form " + Display.getInstance().getCurrent().getName());
    Log.e((Throwable)evt.getSource());
    Log.sendLog();
}});

但是 1) 没有堆栈跟踪和 2) Log.sendLog 需要订阅。我是一个个体经营的爱好者,在我生命中的这个阶段,我负担不起订阅费用。我尝试了几种通常在 Java 中使用的途径:

   ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
   PrintStream ps = new PrintStream(baos);
   System.setOut(ps);

唉,CodenameOne 中没有 System.setOut。但是,在 Throwable 中有一个 StackTraceElement[]!

   for (StackTraceElement ste: throwable.getStackTrace()) {
      container.add(new SpanLabel(ste.toString()));
   }

不,不编译。 StackTraceElement 根据我的 IDE(可能来自 Java 8)和 github 上的源代码(https://github.com/codenameone/CodenameOne/blob/master/vm/JavaAPI/src/java/lang/Throwable.java)出现在 Throwable 中,但是 CLDC11.jar 中的代码没有。无论哪种方式,java.lang.StackTraceElement 都不是 CodenameOne 发行版的一部分,并且不受支持。当然会很方便(阅读功能请求)!

虽然 CodenameOne 有一个弹出对话框的内置错误处理程序很方便,但该错误对最终用户毫无用处,因为他们不知道这意味着什么,并且对于没有堆栈跟踪的开发人员来说毫无用处。在我的情况下,错误只发生在设备上而不是模拟器上,所以我可以告诉我没有办法访问堆栈跟踪。对吗?

功能请求:在错误处理对话框中包含堆栈跟踪(即使作为可扩展的 + 列表)和/或包含从代码中获取堆栈跟踪的方法。尽我所能告诉堆栈跟踪只能转到标准输出。感谢您阅读所有内容!

【问题讨论】:

  • 将它添加到对话框的主要问题是我们只实现了 Log.e() 并且实现是本机的,因此我们实际上没有作为字符串的堆栈跟踪。我没有尝试过尼克的建议,但它可能对你有用。您还可以将电缆连接到 iOS 设备以查看 Android 中的打印输出,但您需要带有 xcode 的 Mac。我听说在 Windows 上有一些技巧可以做到这一点,但我没有尝试过。

标签: exception codenameone throwable


【解决方案1】:

Android 很简单,因为您可以使用 logcat,但对于 iOS,我通常将带有调试信息的字符串存储在存储空间中,您可以设置一个按钮(在工具栏中)以将日志显示为弹出对话框或新表单,以便更容易阅读。

Storage storage = Storage.getInstance();
String log = (String) storage.readObject("debugLog");
log += "your debug string\n";
storage.writeObject("debugLog", log);

或者您可以使用首选项

Preferences.set("debugLog", Preferences.get("debugLog", null) + "your debug string" + "\n");

【讨论】:

  • 存储这样的日志是个好主意,而且很容易存储不同运行的日志。很容易将这些日志的名称存储为“目录”并制作我自己的基于时间的小文件系统。谢谢尼克,尽管诅咒调试已经变成了再次放入一堆打印语句。 =)
【解决方案2】:

这个 hack 以字符串形式获取堆栈跟踪

class LogCapture extends Log
{   Log oldLog;
    StringWriter myWriter;
    LogCapture() 
    { oldLog = Log.getInstance();
      install(this);  
    }
    protected Writer createWriter() throws IOException 
    {   return(myWriter = new StringWriter());
    }
    public String dispose()
    {
        install(oldLog);
        return(myWriter.toString());
    }
}

然后

    public static String getStackTrace(Throwable t)
{
    LogCapture cap = new LogCapture();
    Log.e(t);
    return cap.dispose();   
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    相关资源
    最近更新 更多