OutputStream not writing mp3 fully - java

public void getMp4FromYoutube(String httpPath, String absolutePath, String jobName, String email) {
try {
byte[] mp3ByteArray = youtubeToMP3(httpPath);
File mp3File = new File("src/main/resources/audio.mp3");
OutputStream os = new FileOutputStream(mp3File);
os.write(mp3ByteArray);
os.flush();
os.close();
convertToBase64AndSend(jobName, mp3File, email);
} catch (IOException e) {
e.printStackTrace();
}
}
In my method, I need it to write an mp3 of a youTube page. For anyone who is worrying, its not to copy videos - I've written a transcription that I want to now download the audio, translate, and delete. When I run this method without continuing the code (though commenting out convertToBase64AndSend) it downloads the whole video audio. However, when I continue to the convertToBase64AndSend method to continue with the translation it only downloads one second of the audio. I'm assuming its something to do with the OutputStream and the way I'm using it? If anybody has any ideas I'd be very grateful. Thanks.

Rather than calling the convertToBase64AndSend method in the getMp4FromYoutube method I called it in the class that had called getMp4FromYouTube. Worked for some reason but I have no idea why! Anybody can give me an explanation I'd be grateful!

Related

Saving to "ExternalStorage" - Processing library

Stackoverflowers,
I am doing a simple project using Android smartphones to create 3D forms. I am using Android Processing to make a simple App.
My code makes a 3D shape and saves it as an .STL file. It works on my laptop and saves the .STL file, but in the App. version, I need it to save to the External storage/SD Card of my phone (HTC Sensation). It does not, because of the way the “save” function (writeSTL) in the Processing library I am using has been written.
I have posted for help here (my code more complete code is here too):
http://forum.processing.org/two/discussion/4809/exporting-geometry-stl-obj-dfx-modelbuilder-and-android
...and Marius Watz who wrote the library says that the writeSTL() code is pretty much standalone and the only thing missing is (or should be) replacing the code creating the output stream, which needs to be modified to work with Android. Basically, this line:
FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));
I am not a great programmer in that I can usually get Processing to do what I need to do but no more; this problem has me beaten. I am looking for ideas for the correct code to replace the line:...
FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));
...with something “Android-friendly”. Calling getExternalStorageDirectory() should work but I am at a loss to find the correct structure.
The code for the writeSTL function is below.
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();
}
}
Any suggestions are gratefully received.
Thank you in advance.
There are a few ways of doing this - some that will just work and some that are proper ... as with all things Processing/Java. It's really not that different from regular Java though - the only quirk is the root SD path, and checking if it exists or not (note that some phones have "internal" rather than "external" storage (i.e. not removable/swappable), but Android should interpret these the same AFAIK.
In classic Java fashion, you should really be checking IF the SD Card is present beforehand... I use the following structure, taken from this answer by #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
}
Note that he provides a full class for you to use, which is great, and has a few convenience functions.
The second thing you might want to look at is creating a custom directory on the SD Card of the device, probably in setup() - something like this:
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();
}
Of course, instead of HardCoding the Path name, you should do something like
String dirName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyAppName";
instead...
Also, note that the above try/catch should go INSIDE the case statement of "if (state.equals(Environment.MEDIA_MOUNTED))" ... or should be wrapped in a separate function anc called from there.
Then, finally, saving it. If you wanted to use a BufferedWriter, it would look like this:
BufferedWriter writer = new BufferedWriter(new FileWriter(dirName, true));
writer.write(STL_STUFF);
writer.flush();
writer.close();
I've only use a FileOutputStream within a BufferedOutput Stream, and it looked like this:
try {
String fileName = "SOME_UNIQUE_NAME_PER_FILE";
String localFile = dirName + "/" +filename;
OutputStream output = new BufferedOutputStream(newFileOutputStream(localFile));
}
catch(Exception e) {
e.printStackTrace();
}
Finally, give my regards to Marius if you talk to him! ;-)

Local Jetty6 cannot read image from byte array (ByteArrayInputStream) using ImageIO

Hi Stackoverflow members,
for some time we switched in out GWT application, the GWT version from 2.4 to 2.6.
So we also changed to the new super dev mode there. With this we needed to install
an local jetty server and could not use the internal eclipse ?jetty? anymore.
On the server side we are writing and saving images with the ImageIO package from
sun itself. Till last week, there were no problems with this, but then we checked
that our app is not anymore able to read from bytearrayinputstream in the case as
it does on our deployment servers. For reliable development we need the possibility
to code and test on a local platform.
The problem is, that ImageIO.read static function does not work anymore, but it
does not only don't work anymore, it exits the code WITHOUT to throw an exception!
I will now show you the code part:
System.out.println("createImage..."+file+", "+response+", fib"+fileInBytes+" fibs:"+fileInBytes.length);
ETFile f = file;
boolean isImage = false;
BufferedImage image = null;
try {
System.out.println("read1...");
ByteArrayInputStream bais = new ByteArrayInputStream(fileInBytes);
System.out.println("read2..."+bais);
image = ImageIO.read(bais);
//ByteArrayOutputStream baos = new ByteArrayOutputStream();
//baos.write(fileInBytes);
//saveStreamToFile(filename+"_bla.jpg", baos, data);
//baos.close();
bais.close();
System.out.println("read2.5...");
if (image != null) {
System.out.println("read2.6...");
isImage = true;
}
System.out.println("read3...");
} catch (/*IO*/Exception e) {
System.out.println("read4...");
System.out.println(e.getLocalizedMessage());
e.printStackTrace();
} finally {
System.out.println("read4.5...");
}
System.out.println("isimage:"+isImage);
I'm getting only the following output:
read1...
read2...java.io.ByteArrayInputStream#15bea4b
But no:
System.out.println("read2.5...");
System.out.println("read2.6...");
System.out.println("read3...");
System.out.println("read4...");
nor
System.out.println("read4.5...");
As you see, i can write the bytestream s file to filesystem, but
can't read that bytestream with ImageIO.read to an image.
And I don't know why. The bytestream is there, has a size and writing
it to disk is also correct, but if I use ImageIO.read the server somehow
exits the code without any exception..
Do someone know, was is going wrong here?
Thank you.
Regards,
Max
edit attached stack trace
thread:1323900765#qtp-433064372-0:java.lang.ClassLoader$NativeLibrary.load(Native Method)
thread:1323900765#qtp-433064372-0:java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1833)
thread:1323900765#qtp-433064372-0:java.lang.ClassLoader.loadLibrary(ClassLoader.java:1730)
thread:1323900765#qtp-433064372-0:java.lang.Runtime.loadLibrary0(Runtime.java:823)
thread:1323900765#qtp-433064372-0:java.lang.System.loadLibrary(System.java:1044)
thread:1323900765#qtp-433064372-0:sun.security.action.LoadLibraryAction.run(LoadLibraryAction.java:50)
thread:1323900765#qtp-433064372-0:java.security.AccessController.doPrivileged(Native Method)
thread:1323900765#qtp-433064372-0:java.awt.Toolkit.loadLibraries(Toolkit.java:1605)
thread:1323900765#qtp-433064372-0:java.awt.Toolkit.<clinit>(Toolkit.java:1627)
thread:1323900765#qtp-433064372-0:sun.awt.AppContext$2.run(AppContext.java:240)
thread:1323900765#qtp-433064372-0:sun.awt.AppContext$2.run(AppContext.java:226)
thread:1323900765#qtp-433064372-0:java.security.AccessController.doPrivileged(Native Method)
thread:1323900765#qtp-433064372-0:sun.awt.AppContext.initMainAppContext(AppContext.java:226)
thread:1323900765#qtp-433064372-0:sun.awt.AppContext.access$200(AppContext.java:112)
thread:1323900765#qtp-433064372-0:sun.awt.AppContext$3.run(AppContext.java:306)
thread:1323900765#qtp-433064372-0:java.security.AccessController.doPrivileged(Native Method)
thread:1323900765#qtp-433064372-0:sun.awt.AppContext.getAppContext(AppContext.java:287)
thread:1323900765#qtp-433064372-0:javax.imageio.spi.IIORegistry.getDefaultInstance(IIORegistry.java:137)
thread:1323900765#qtp-433064372-0:javax.imageio.ImageIO.<clinit>(ImageIO.java:48)
thread:1323900765#qtp-433064372-0:com.et.eb.server.servlets.ETFileUploadServlet.createImage(ETFileUploadServlet.java:441)
thread:1323900765#qtp-433064372-0:com.et.eb.server.servlets.ETFileUploadServlet.writeImage(ETFileUploadServlet.java:285)
thread:1323900765#qtp-433064372-0:com.et.eb.server.servlets.ETFileUploadServlet.readFormData(ETFileUploadServlet.java:364)
thread:1323900765#qtp-433064372-0:com.et.eb.server.servlets.ETFileUploadServlet.doPost(ETFileUploadServlet.java:122)
thread:1323900765#qtp-433064372-0:javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
thread:1323900765#qtp-433064372-0:javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:401)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.Server.handle(Server.java:326)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:945)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
thread:1323900765#qtp-433064372-0:org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
thread:1323900765#qtp-433064372-0:org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
thread:1323900765#qtp-433064372-0:org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

Problems with facebooks conceal library

I'm having issues with reading decrypted data from conceal. It looks like I can't correctly finish streaming.
I pretend there is some issue with conceal, because of when I switch my proxyStream (just the encryption part) to not run it through conceal, everything works as expected. I'm also assuming that writing is ok, there is no exception whatsoever and I can find the encrypted file on disk.
I'm proxying my data through contentprovider to allow other apps read decrypted data when the user wants it. (sharing,...)
In my content provider I'm using the openFile method to allow contentResolvers read the data
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
try {
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
String name = uri.getLastPathSegment();
File file = new File(name);
InputStream fileContents = mStorageProxy.getDecryptInputStream(file);
ParcelFileDescriptor.AutoCloseOutputStream stream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);
PipeThread pipeThread = new PipeThread(fileContents, stream);
pipeThread.start();
return pipe[0];
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
I guess in the Facebook app Facebook android team could be rather using a standard query() method with a byte array sent in MediaStore.MediaColumns() which is not suitable for me because of I'm not only encrypting media files and I also like the approach of streams better.
This is how I'm reading from the Inpustream. It's basically a pipe between two parcelFileDescriptors. The inputstream comes from conceal and it is a FileInputstream wrapped into a BufferedInputStream originaly.
static class PipeThread extends Thread {
InputStream input;
OutputStream out;
PipeThread(InputStream inputStream, OutputStream out) {
this.input=inputStream;
this.out=out;
}
#Override
public void run() {
byte[] buf=new byte[1024];
int len;
try {
while ((len=input.read(buf)) > 0) {
out.write(buf, 0, len);
}
input.close();
out.flush();
out.close();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(),
"Exception transferring file", e);
}
}
}
I've tried other methods how to read the stream, so it really shouldn't be the issue.
Finally here's the exception I'm constantly ending up with. Do you know what could be the issue? It points to native calls, which I got lost in..
Exception transferring file
com.facebook.crypto.cipher.NativeGCMCipherException: decryptFinal
at com.facebook.crypto.cipher.NativeGCMCipher.decryptFinal(NativeGCMCipher.java:108)
at com.facebook.crypto.streams.NativeGCMCipherInputStream.ensureTagValid(NativeGCMCipherInputStream.java:126)
at com.facebook.crypto.streams.NativeGCMCipherInputStream.read(NativeGCMCipherInputStream.java:91)
at com.facebook.crypto.streams.NativeGCMCipherInputStream.read(NativeGCMCipherInputStream.java:76)
EDIT:
It looks like the stream is working ok, but what fails is the last iteration of reading from it. As I'm using buffer it seems like the fact that the buffer is bigger then the amount of remaiming data is causing the issue. I've been looking into sources of conceal and it seems to be ok from this regard there. Couldn't it be failing somewhere in the native layer?
Note: I've managed to get the decrypted file except its final chunk of bytes..So I have for example an incomplete image file (with last few thousands of pixels not being displayed)
From my little experience with conceal, I have noticed that, only the same application that encrypts a file could decrypt it successfully irrespective whether it has the same package or not. Be sure to put this in mind
This was resolved in https://github.com/facebook/conceal/issues/24. For posterity's sake, the problem here is that the author forgot to call close() on the output stream.

NFC with NFC-Tools, Creating NDEF Application

I am attempting to do what I would have guessed would be pretty simple, but as it turns out is not. I have an ACR122 NFC reader and a bunch of Mifare Classic and Mifare Ultralight tags, and all I want to do is read and write a mime-type and a short text string to each card from a Java application. Here's what I've got working so far:
I can connect to my reader and listen for tags
I can detect which type of tag is on the reader
On the Mifare Classic tags I can loop through all of the data on the tag (after programming the tag from my phone) and build an ascii string, but most of the data is "junk" data
I can determine whether or not there is an Application directory on the tag.
Here's my code for doing that:
Main:
public static void main(String[] args){
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals;
try{
TerminalHandler handler = new TerminalHandler();
terminals = factory.terminals().list();
CardTerminal cardTerminal = terminals.get(0);
AcsTerminal terminal = new AcsTerminal();
terminal.setCardTerminal(cardTerminal);
handler.addTerminal(terminal);
NfcAdapter adapter = new NfcAdapter(handler.getAvailableTerminal(), TerminalMode.INITIATOR);
adapter.registerTagListener(new CustomNDEFListener());
adapter.startListening();
System.in.read();
adapter.stopListening();
}
catch(IOException e){
}
catch(CardException e){
System.out.println("CardException: " + e.getMessage());
}
}
CustomNDEFListener:
public class CustomNDEFListener extends AbstractCardTool
{
#Override
public void doWithReaderWriter(MfClassicReaderWriter readerWriter)
throws IOException{
NdefMessageDecoder decoder = NdefContext.getNdefMessageDecoder();
MadKeyConfig config = MfConstants.NDEF_KEY_CONFIG;
if(readerWriter.hasApplicationDirectory()){
System.out.println("Application Directory Found!");
ApplicationDirectory directory = readerWriter.getApplicationDirectory();
}
else{
System.out.println("No Application Directory Found, creating one.");
readerWriter.createApplicationDirectory(config);
}
}
}
From here, I seem to be at a loss as for how to actually create and interact with an application. Once I can create the application and write Record objects to it, I should be able to write the data I need using the TextMimeRecord type, I just don't know how to get there. Any thoughts?
::Addendum::
Apparently there is no nfc-tools tag, and there probably should be. Would someone with enough rep be kind enough to create one and retag my question to include it?
::Second Addendum::
Also, I am willing to ditch NFC-Tools if someone can point me in the direction of a library that works for what I need, is well documented, and will run in a Windows environment.
Did you checked this library ? It is well written, how ever has poor documentation. Actually no more than JavaDoc.

Problems writing to a unix pipe through Java

I am writing to a framebuffer located at "/dev/fb0". Everything works fine until I try to write again to the pipe using an OutputStream, which hangs the program. I have resolved this by closing the output stream and then recreating it, but this seems awfully slow and blunt.
Framebuffer.java
public class Framebuffer extends Autobuffer {
private FileOutputStream out = null;
private File pipe = null;
public Framebuffer() {
super(320, 240);
}
public Framebuffer(File pipe) {
super(320, 240);
try {
out = new FileOutputStream(pipe);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
this.pipe = pipe;
}
public void sync() throws IOException {
out.write(getBytes());
out.close();
out = new FileOutputStream(pipe);
}
}
Any ideas?
Thanks.
Firstly, unless something really weird is going on, "/dev/fb0" is a device file not a pipe. [This is a nitpick, but if you use the wrong terminology, 1) people won't understand you and 2) you will have difficulty searching for answers.]
Secondly, this looks like a weird way to interact with a framebuffer!!
I suspect that the problem is that you need to do the equivalent of a POSIX lseek call to set the stream position to zero each time you draw a frame. I've found two ways to do this:
Use RandomAccessFile instead of OutputStream / FileOutputStream, and call seek(long) to seek the file.
Call FileOutputStream.getChannel(), and then use position(long) to seek the file.
Changing the Output Stream to RandomAccessFile fixed all of my problems. I bet the stream wasn't working because it can't seek to position 0. Thanks to all who replied.
What if you flush your output with flush (from OutputStream)?

Categories

Resources