LibGDX:从Android的Web地址下载和加载模型

时间:2015-06-13 09:29:33

标签: android libgdx

我的服务器上保存了一个g3db模型文件(例如http://website.com/model.g3db)。我想将该模型加载到我的Android应用程序中。

我在我的启动器类中尝试过asyncTask,首先在本地下载文件,然后使用下载的文件加载模型。但它没有用。

AndroidLauncher.java

public class AndroidLauncher extends AndroidApplication {

public final static String FILENAME = "model";
public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
private ProgressDialog mProgressDialog;

private LinearLayout modelView;

private Viewer viewer; // Viewer Class

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.viewer);

    modelView = (LinearLayout) findViewById(R.id.view);

    startDownload();
}

private void startDownload() {
    String url = "http://website.com/model.g3db";
    new DownloadFileAsync().execute(url);
}

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
        case DIALOG_DOWNLOAD_PROGRESS:
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setMessage("Downloading file..");
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.setCancelable(false);
            mProgressDialog.show();
            return mProgressDialog;
        default:
            return null;
    }
}

class DownloadFileAsync extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        file = new File(getFilesDir(), FILENAME);
        showDialog(DIALOG_DOWNLOAD_PROGRESS);
    }

    @Override
    protected String doInBackground(String... aurl) {
        int count;
        try {
            URL url = new URL(aurl[0]);
            URLConnection conexion = url.openConnection();
            conexion.connect();

            int lenghtOfFile = conexion.getContentLength();
            Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile);

            InputStream input = new BufferedInputStream(url.openStream());
            OutputStream output = openFileOutput(FILENAME, Context.MODE_PRIVATE);

            byte data[] = new byte[1024];

            long total = 0;

            while ((count = input.read(data)) != -1) {
                total += count;
                publishProgress(""+(int)((total*100)/lenghtOfFile));
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (Exception e) {
            Toast.makeText(AndroidLauncher.this, "File Writing Problem", Toast.LENGTH_LONG).show();
        }
        return null;

    }
    protected void onProgressUpdate(String... progress) {
        Log.d("ANDRO_ASYNC",progress[0]);
        mProgressDialog.setProgress(Integer.parseInt(progress[0]));
    }

    @Override
    protected void onPostExecute(String unused) {
        dismissDialog(DIALOG_DOWNLOAD_PROGRESS);

        // Now Initialize Viewer class as we have the model downloaded locally
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        config.useGLSurfaceView20API18 = true;
        viewer = new Viewer();
        modelView.addView(initializeForView(viewer, config));
    }
}

Viewer.java

private FileHandle fileHandle;
private ModelLoader modelLoader;

@Override
public void create () {
    stage = new Stage();
    font = new BitmapFont();
    label = new Label(" ", new Label.LabelStyle(font, Color.WHITE));

    stage.addActor(label);
    stringBuilder = new StringBuilder();

    modelBatch = new ModelBatch();
    environment = new Environment();
    environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
    environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));

    cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    cam.position.set(10,21,0);
    cam.lookAt(0,0,0);
    cam.up.set(Vector3.Y);
    cam.near = 5;
    cam.far = 70;
    cam.update();

    camController = new CameraInputController(cam);
    Gdx.input.setInputProcessor(new InputMultiplexer(this, camController));

    // Locally Stored Model File -----
    handle = Gdx.files.local("model.g3db");

    UBJsonReader jsonReader = new UBJsonReader();
    modelLoader = new G3dModelLoader(jsonReader);

    loading = true;
}

private void doneLoading () {
    Model model = modelLoader.loadModel(fileHandle);

    for (int i = 0; i < model.nodes.size; i++) {
        String id = model.nodes.get(i).id;
        GameObject instance = new GameObject(model, id, true);
        instances.add(instance);
    }
    loading = false;
}

但是当我运行应用程序时出现错误

java.lang.RuntimeException: Unable to resume activity {in.SpaceFix.SpaceFix.android/in.SpaceFix.SpaceFix.android.AndroidLauncher}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.badlogic.gdx.backends.android.AndroidInput.onResume()' on a null object reference
              at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3137)
              at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3168)
              at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2522)
              at android.app.ActivityThread.access$800(ActivityThread.java:162)
              at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1412)
              at android.os.Handler.dispatchMessage(Handler.java:106)
              at android.os.Looper.loop(Looper.java:189)
              at android.app.ActivityThread.main(ActivityThread.java:5530)
              at java.lang.reflect.Method.invoke(Native Method)
              at java.lang.reflect.Method.invoke(Method.java:372)
              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:950)
              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)
       Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.badlogic.gdx.backends.android.AndroidInput.onResume()' on a null object reference
              at com.badlogic.gdx.backends.android.AndroidApplication.onResume(AndroidApplication.java:293)
              at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1246)
              at android.app.Activity.performResume(Activity.java:6052)
              at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3122)
              at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3168)
              at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2522)
              at android.app.ActivityThread.access$800(ActivityThread.java:162)
              at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1412)
              at android.os.Handler.dispatchMessage(Handler.java:106)
              at android.os.Looper.loop(Looper.java:189)
              at android.app.ActivityThread.main(ActivityThread.java:5530)
              at java.lang.reflect.Method.invoke(Native Method)
              at java.lang.reflect.Method.invoke(Method.java:372)
              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:950)
              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)

请帮助!

1 个答案:

答案 0 :(得分:2)

看起来你推迟创建你的ApplicationListener,它不会工作。 AndroidApplication期望有效ApplicationListener。使其看起来像this

@Override
protected void onCreate (Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
    config.useGLSurfaceView20API18 = true;
    viewer = new Viewer();
    modelView.addView(initializeForView(viewer, config));
}

另外,你应该use an interface to use platform specific code。但是,如果你真的想走上你走的路,那么你可以告诉你的观众你已经完成了下载:

viewer.downloadComplete();

Viewer课程中,您可以在该方法中下载需要执行的特定代码:

public void downloadComplete()
{
    handle = Gdx.files.local("model.g3db");
    UBJsonReader jsonReader = new UBJsonReader();
    modelLoader = new G3dModelLoader(jsonReader);
    Model model = modelLoader.loadModel(fileHandle);
    for (int i = 0; i < model.nodes.size; i++) {
        String id = model.nodes.get(i).id;
        GameObject instance = new GameObject(model, id, true);
        instances.add(instance);
    }
}

顺便说一句,看起来您使用AssetManager获取了my tutorial的代码并对其进行了修改,使其无法理解。您应该使用AssetManager或不需要loadingdoneLoading()机制。

也就是说,应该注意的是,下载文件不是特定于平台的功能,因此可以在ApplicationListener内完成。有关更多信息,请查看HttpRequest课程。这看起来像这样:

Model model;
@Override
public void create () {
    stage = new Stage();
    font = new BitmapFont();
    label = new Label(" ", new Label.LabelStyle(font, Color.WHITE));

    stage.addActor(label);
    stringBuilder = new StringBuilder();

    modelBatch = new ModelBatch();
    environment = new Environment();
    environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
    environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));

    cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    cam.position.set(10,21,0);
    cam.lookAt(0,0,0);
    cam.up.set(Vector3.Y);
    cam.near = 5;
    cam.far = 70;
    cam.update();

    camController = new CameraInputController(cam);
    Gdx.input.setInputProcessor(new InputMultiplexer(this, camController));

    Net.HttpRequest request = new Net.HttpRequest(Net.HttpMethods.GET);
    request.setUrl("http://website.com/model.g3db");
    Gdx.net.sendHttpRequest(request, new HttpResponseListener() {
        @Override
        public void handleHttpResponse (HttpResponse httpResponse) {
            final FileHandle tmpFile = FileHandle.tempFile("model");
            tmpFile.write(httpResponse.getResultAsStream(), false);
            Gdx.app.postRunnable(new Runnable() {
                @Override
                public void run () {
                    model = new G3dModelLoader(new UBJsonReader()).loadModel(tmpFile);
                    for (int i = 0; i < model.nodes.size; i++) {
                        String id = model.nodes.get(i).id;
                        GameObject instance = new GameObject(model, id, true);
                        instances.add(instance);
                    }
                }
            });
        }

        @Override
        public void failed (Throwable t) {
            Gdx.app.error("Test", "something went wrong", t);
        }

        @Override
        public void cancelled () {
            Gdx.app.log("Test", "cancelled");
        }
    });
}

虽然与您的问题无关,但请注意Model需要处理。您正在Model方法中创建新的doneLoading(),但从不处理它。您可能希望重新考虑您的方法,因为它会导致资源泄漏。