Сохранение во ExternalStorage — библиотека обработки

стековерфлауэрс,

Я делаю простой проект, используя Android-смартфоны для создания 3D-форм. Я использую Android Processing для создания простого приложения.

Мой код создает трехмерную форму и сохраняет ее в виде файла .STL. Он работает на моем ноутбуке и сохраняет файл .STL, но в приложении. версию, мне нужно сохранить ее на внешнее хранилище/SD-карту моего телефона (HTC Sensation). Это не так из-за того, как написана функция «сохранения» (writeSTL) в библиотеке обработки, которую я использую.

Я написал здесь для помощи (мой код более полный код здесь тоже):

http://forum.processing.org/two/discussion/4809/exporting-geometry-stl-obj-dfx-modelbuilder-and-android

... и Мариус Ватц, написавший библиотеку, говорит, что код writeSTL() в значительной степени автономен, и единственное, чего не хватает, это (или должно быть) замена кода, создающего поток вывода, который необходимо изменить для работы с Android. В основном, эта строка:

FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));

Я не великий программист в том смысле, что обычно могу заставить Processing делать то, что мне нужно, но не более того; эта проблема меня избила. Я ищу идеи для правильного кода для замены строки:...

FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));

... с чем-то «дружественным к Android». Вызов getExternalStorageDirectory() должен работать, но я не могу найти правильную структуру.

Код функции writeSTL приведен ниже.

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Output binary STL file of mesh geometry.
 * @param p Reference to PApplet instance
 * @param filename Name of file to save to
 */

  public void customWriteSTL(UGeometry geo, PApplet p, String filename) {
  byte [] header;
  ByteBuffer buf;
  UFace f;

  try {
    if (!filename.toLowerCase().endsWith("stl")) filename+=".stl";
    FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));

buf = ByteBuffer.allocate(200);
header=new byte[80];
buf.get(header, 0, 80);
out.write(header);
buf.rewind();

buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putInt(geo.faceNum);
buf.rewind();
buf.get(header, 0, 4);
out.write(header, 0, 4);
buf.rewind();

UUtil.logDivider("Writing STL '"+filename+"' "+geo.faceNum);

buf.clear();
header=new byte[50];
if (geo.bb!=null) UUtil.log(geo.bb.toString());

for (int i=0; i<geo.faceNum; i++) {
  f=geo.face[i];
  if (f.n==null) f.calcNormal();

  buf.rewind();
  buf.putFloat(f.n.x);
  buf.putFloat(f.n.y);
  buf.putFloat(f.n.z);

  for (int j=0; j<3; j++) {
    buf.putFloat(f.v[j].x);
    buf.putFloat(f.v[j].y);
    buf.putFloat(f.v[j].z);
  }

  buf.rewind();
  buf.get(header);
  out.write(header);
}

out.flush();
out.close();
UUtil.log("Closing '"+filename+"'. "+geo.faceNum+" triangles written.\n");
  } 
  catch (Exception e) {
e.printStackTrace();
  }
}

Любые предложения принимаются с благодарностью.

Заранее спасибо.


person PDF    schedule 29.06.2014    source источник
comment
Думайте, что вам нужно только адаптировать p.sketchPath() для использования getExternalStorageDirectory() или еще лучше getExternalFilesDir(). При условии, что .getOutputStream() выберет полный путь.   -  person greenapps    schedule 29.06.2014
comment
Если нет, то используйте FileOutputStream = new FileOutputStream(p.sketchPath(filename)):.   -  person greenapps    schedule 29.06.2014
comment
Действительно, это (ваш первый ответ) был путь, по которому мне нужно было идти. Спасибо за ваш вклад @greenapps   -  person PDF    schedule 07.07.2014


Ответы (1)


Есть несколько способов сделать это - некоторые из них будут просто работать, а некоторые правильно ... как и все, что связано с Processing/Java. Хотя на самом деле это не так уж отличается от обычной Java - единственная особенность - это корневой путь SD и проверка его существования или нет (обратите внимание, что некоторые телефоны имеют «внутреннее», а не «внешнее» хранилище (т.е. несъемное/заменяемое), но Android должен интерпретировать их одинаково, AFAIK.

В классической манере Java вам действительно следует заранее проверить IF SD-карту... Я использую следующую структуру, взятую из этот ответ от @kaolick

    String state = Environment.getExternalStorageState();
    if (state.equals(Environment.MEDIA_MOUNTED)) {
        // Storage is available and writeable - ALL GOOD  
    } else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
        // Storage is only readable - RUH ROH
    } else {
        // Storage is neither readable nor writeable - ABORT    
    }

Обратите внимание, что он предоставляет полный класс для использования, и это здорово, и у него есть несколько удобных функций.

Второе, на что вы, возможно, захотите обратить внимание, — это создание пользовательского каталога на SD-карте устройства, возможно, в setup() — что-то вроде этого:

  try{
    String dirName = "//sdcard//MyAppName";
    File newFile = new File(dirName);

    if(newFile.exists() && newFile.isDirectory()) {
      println("Directory Exists... All Good");
    } 
    else {
      println("Directory Doesn't Exist... We're Making It");
      newFile.mkdirs();
    }
  }
  catch(Exception e) {
    e.printStacktrace();
  }

Конечно, вместо жесткого кодирования имени пути вы должны сделать что-то вроде

String dirName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyAppName";

вместо...

Также обратите внимание, что приведенная выше попытка/поймать должна идти ВНУТРИ оператора case «if (state.equals(Environment.MEDIA_MOUNTED))»… или должна быть заключена в отдельную функцию и вызываться оттуда.

Затем, наконец, сохранить его. Если вы хотите использовать BufferedWriter, это будет выглядеть так:

  BufferedWriter writer = new BufferedWriter(new FileWriter(dirName, true));
  writer.write(STL_STUFF);
  writer.flush();
  writer.close();

Я использовал только FileOutputStream в BufferedOutput Stream, и это выглядело так:

try {
    String fileName = "SOME_UNIQUE_NAME_PER_FILE";
    String localFile = dirName + "/" +filename;
    OutputStream output = new BufferedOutputStream(newFileOutputStream(localFile));
}
catch(Exception e) {
    e.printStackTrace();
}

Наконец, передай привет Мариусу, если поговоришь с ним! ;-)

person jesses.co.tt    schedule 29.06.2014
comment
Два голоса за вопрос, но ни одного за ответ?!? - person jesses.co.tt; 03.07.2014
comment
Большое-большое спасибо за ваш ответ @jesses.co.tt - вы замечательный человек. Я был за границей и не имел возможности прочитать это. Ваш исчерпывающий ответ указал мне правильное направление. Нужно 100 голосов - к сожалению, я сам не могу голосовать за него :( - person PDF; 07.07.2014
comment
лол, хорошо, спасибо ... спасибо, что принял ответ. проголосуйте, когда у вас будет возможность, и отметьте меня напрямую, если у вас есть какие-либо вопросы по P5/Droid! - person jesses.co.tt; 08.07.2014