在libGDX / RoboVM项目中使用MFMailComposeViewController构建错误

时间:2014-06-18 20:44:10

标签: java libgdx robovm

我尝试向现有iOS libGDX应用添加功能(使用RoboVM),以便在按下scene2d.ui按钮时,会显示MFMailComposeViewController弹出窗口,其中附加了一组预定义的CSV文件。应用程序库>本地文件夹。这是我到目前为止的代码:

进口&成员:

import org.robovm.apple.foundation.*;
import org.robovm.apple.messageui.MFMailComposeResult;
import org.robovm.apple.messageui.MFMailComposeViewController;
import org.robovm.apple.messageui.MFMailComposeViewControllerDelegate;
import org.robovm.apple.uikit.*;
import org.robovm.objc.ObjCObject;

private UIWindow mailWindow;
private UIViewController mailViewController;
private MFMailComposeViewController mailPicker;

方法:

private void createMailWindow() 
{
    mailWindow = new UIWindow(UIScreen.getMainScreen().getBounds());
    mailViewController = new UIViewController();
    mailWindow.setRootViewController(mailViewController);
}

private void sendEmail(String fileName, String subject, String body) 
{
    mailPicker = new MFMailComposeViewController();
    mailPicker.addStrongRef(mailWindow);
    String path = NSBundle.getMainBundle().getResourcePath();

    if (fileName != null)
    {
        path = path.substring(0, path.lastIndexOf('/')) + "/Library/local/" + fileName;
    }

        MFMailComposeViewControllerDelegate delegate = new MFMailComposeViewControllerDelegate()
        {
            public void mailComposeControllerDidFinish(MFMailComposeViewController controller, MFMailComposeResult result, NSError error) 
            {
                controller.dismissViewController(true, null);
                mailPicker.removeFromParentViewController();
                mailPicker.removeStrongRef(mailWindow);
                mailWindow.setHidden(true);
                mailPicker = null;
            }

            @Override
            public void didFinish(MFMailComposeViewController controller, MFMailComposeResult result, NSError error) 
            {

            }
        };

        mailPicker.setMailComposeDelegate(delegate);
        mailPicker.addStrongRef((ObjCObject) delegate);

        if (fileName != null)
        {
                // attach CSVs here...
        }

        mailPicker.setSubject((subject != null ? subject : "Test Results"));
        mailPicker.setMessageBody((body != null ? body : "Please find attached the latest results data."), false);

        if (MFMailComposeViewController.canSendMail())
        {
            mailWindow.getRootViewController().presentViewController(mailPicker, true, null);
            mailWindow.makeKeyAndVisible();
        }
    }
}

我已经准备好了这个代码,在尝试构建之前Eclipse没有标记任何问题,因此我收到以下错误:

Exception in thread "main" java.lang.NoClassDefFoundError: org/robovm/rt/bro/NativeObject
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at com.mmu.cfa.DesktopMain.main(DesktopMain.java:26)
Caused by: java.lang.ClassNotFoundException: org.robovm.rt.bro.NativeObject
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 49 more

我已将RoboVM Cocoa Touch Library和RoboVM Runtime Library添加到我的主项目的构建路径中。如果我删除这两个方法,我的项目构建没有错误。我还需要设置其他东西才能让它运行起来吗?

1 个答案:

答案 0 :(得分:1)

问题

在Libgdx应用程序中,所有支持平台的项目共享主项目

所以主项目必须包含与平台无关的代码

RoboVM Cocoa Touch Library RoboVM运行时库是平台相关的,只能在iOS上运行,而不能在桌面,android,html等上运行。


解决方案

  1. 从主项目中删除 RoboVM Cocoa Touch Library RoboVM Runtime Library 依赖项。
  2. 将这些依赖项添加到RoboVM项目中。 (如果他们不在场。)
  3. 创建一个界面,代表您在主项目中所需的功能

    public interface EmailHandler {
        public void createMailWindow();
        public void sendEmail(String fileName, String subject, String body);
    }
    
  4. 使用您已编写的代码在robovm项目中创建一个实现类

    public class RobovmEmailHandler implements EmailHandler {
    
        @Override
        public void createMailWindow() {
            // Your code goes here.
        }
    
        @Override
        public void sendEmail(String fileName, String subject, String body) {
            // Your code goes here.
        }
    }
    
  5. EmailHandler 参数添加到ApplicationListener的构造函数(主项目中的主游戏类)。

    public class MyAwesomeGame extends Game {
    
        private EmailHandler emailHandler; // Use it wherever you like.
    
        public MyAwesomeGame(EmailHandler emailHandler) {
            this.emailHandler = emailHandler;
            // Rest of constructor.
        }
    }
    
  6. 提供 RobovmLauncher(robovm项目的主要类)中的实施参数

    public class RobovmLauncher extends IOSApplication.Delegate {
    
        @Override
        protected IOSApplication createApplication() {
            EmailHandler emailHandler = new RobovmEmailHandler();
            IOSApplicationConfiguration config = new IOSApplicationConfiguration();
            return new IOSApplication(new MyAwesomeGame(emailHandler), config);
        }
    }
    

  7. 注意:
    其他平台的项目会开始大喊你向他们提供EmailHandler。这很自然,也很有预期。您应该为要定位的每个平台提供特定于平台的接口实现。

    希望这有帮助。
    祝你好运。