Downloaded mp3 file in android throwing IOException - android

I am using the below code to download an mp3 file from my server to android
public class DownloadService extends IntentService {
private int result = Activity.RESULT_CANCELED;
public static final String RESULT = "result";
public static final String NOTIFICATION = "!##$%%^";
public DownloadService() {
super("DownloadService");
}
// will be called asynchronously by Android
#Override
protected void onHandleIntent(Intent intent) {
Integer serverTrackId=intent.getIntExtra(Constants.INTENT_PARAM_SERVER_TRACK_ID, 0);
String serverUrl=intent.getStringExtra(Constants.INTENT_PARAM_SERVER_TRACK_URL);
String trackName=intent.getStringExtra(Constants.INTENT_PARAM_SERVER_TRACK_NAME);
String filePath=intent.getStringExtra(Constants.INTENT_PARAM_ROOT_FILE_PATH);
Integer localTrackId=intent.getIntExtra(Constants.INTENT_PARAM_LOCAL_TRACK_ID, 0);
File output = new File(filePath+"/"+trackName);
if (output.exists()) {
result = Activity.RESULT_OK;
publishResults(output.getAbsolutePath(), result);
}
else {
InputStream stream = null;
FileOutputStream fos = null;
try {
URL url = new URL(serverUrl);
stream = url.openConnection().getInputStream();
InputStreamReader reader = new InputStreamReader(stream);
fos = new FileOutputStream(output.getPath());
int next = -1;
while ((next = reader.read()) != -1) {
fos.write(next);
}
// successfully finished
result = Activity.RESULT_OK;
} catch (Exception e) {
e.printStackTrace();
result = Activity.RESULT_CANCELED;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
result = Activity.RESULT_CANCELED;
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
result = Activity.RESULT_CANCELED;
e.printStackTrace();
}
}
}
publishResults(output.getAbsolutePath(), result);
}
}
private void publishResults(String outputPath, int result) {
try {
FileInputStream fileInputStream = new FileInputStream(outputPath);
Intent intent = new Intent(NOTIFICATION);
intent.putExtra(FILEPATH, outputPath);
intent.putExtra(RESULT, result);
sendBroadcast(intent);
}catch(Exception e){
e.printStackTrace();
}
}
}
After downloaded broadcast is made , and I try to play the mp3 file by the below code
if (trackPath != null) {
FileInputStream fileInputStream = new FileInputStream(trackPath);
mediaPlayer.setDataSource(fileInputStream.getFD());
} else {
AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.spacer_audio);
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
}
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mediaPlayer.setLooping(false);
mediaPlayer.prepare();
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.start();
I get IOException thrown from "mediaPlayer.prepare()"
I tried to play the downloaded music file through android default music player and it shows "cannot play this media".
I tried copying it to computer to try play it and I noticed there is a size difference of several KBs from the original track and the downloaded one.
Please help me find the bug.

You use InputStreamReader to read a binary file, it may produce some unexpected problems. I suggest you use BufferedInputStream instead.
BufferedInputStream reader = new BufferedInputStream(stream);
fos = new FileOutputStream(output.getPath());
int length = -1;
byte[] buffer = new byte[1024 * 8];
while ((length = reader.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}

Related

Download file within the app by clicking on the weblink.

I am developing app like playstore in which user can download any app. i have many apps in my application that i got from my website through wp api v2. when we click on any of the available application detail opened and it have a download link. when we click on the link it goes to the browser but what i want is when we click on any of the apps downloading link downloading should start within my app with progress bar. i didn't found any appropriate solution yet on stack or anywhere.
Here is the screenshot attached for better understanding. arrow is pointing to the downloading link.
Try this code, you can put this on click of the link(textview)
private static void downloadFile(String url, File outputFile) {
try {
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile));
fos.write(buffer);
fos.flush();
fos.close();
} catch(FileNotFoundException e) {
return; // swallow a 404
} catch (IOException e) {
return; // swallow a 404
}
}
you can use intent service to download the app.
Here is the code :
public class DownloadService extends IntentService {
File cacheDir;
public DownloadService() {
super("DownloadService");
}
#Override
public void onCreate() {
super.onCreate();
String tmpLocation =
Environment.getExternalStorageDirectory().getPath();
cacheDir = new File(tmpLocation);
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
}
#Override
protected void onHandleIntent(Intent intent) {
String remoteUrl = intent.getExtras().getString("url");
String location;
String filename =
remoteUrl.substring(
remoteUrl.lastIndexOf(File.separator) + 1);
File tmp = new File(cacheDir.getPath()
+ File.separator + filename);
if (tmp.exists()) {
location = tmp.getAbsolutePath();
stopSelf();
return;
}
try {
URL url = new URL(remoteUrl);
HttpURLConnection httpCon =
(HttpURLConnection) url.openConnection();
if (httpCon.getResponseCode() != 200)
throw new Exception("Failed to connect");
InputStream is = httpCon.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1 != (n = is.read(buf))) {
out.write(buf, 0, n);
}
out.close();
is.close();
byte[] response = out.toByteArray();
FileOutputStream fos = new FileOutputStream(tmp);
fos.write(response);
fos.flush();
fos.close();
is.close();
location = tmp.getAbsolutePath();
} catch (Exception e) {
Log.e("Service", "Failed!", e);
}
}
}
Run this service with url passed in the intent

com.googlecode.mp4parser fails for mp3 audio file?

I am using the com.googlecode.mp4parser library to merge audio files. I have an external audio mp3 file which I store in raw resources. This file fails to merge due to following exception, Below is my code :
Reading a file from raw folder :
InputStream is = context.getResources().openRawResource(R.raw.my_mp3_file);
OutputStream output = null;
try {
File file = new File(context.getFilesDir(), "silence.mp3");
if(!file.exists()) {
file.createNewFile();
}
output = new FileOutputStream(file);
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = is.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
output.close();
fileReference= file;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace(); // handle exception, define IOException and others
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Code that reads movie ( Which is failing ) :
if(fileReference.exists()) {
Movie m = new MovieCreator().build(fileReference.getAbsolutePath());
}
While getting this Movie m my code fails throwing the exception :
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.coremedia.iso.boxes.MovieBox.getBoxes(java.lang.Class)' on a null object reference
It works for some mp3 files fails for raw resource files ? What's wrong here ?
Here are my conclusion and solution after a lot of research
MP4Parser for merging audio and video only use .m4a extension
String root = Environment.getExternalStorageDirectory().toString();
String audio = root + "/" + "tests.m4a";
String video = root + "/" + "output.mp4";
String output = root + "/" + "aud_vid.mp4";
mux(video, audio, output);
and here is the method
public boolean mux(String videoFile, String audioFile, String outputFile) {
Movie video;
try {
video = new MovieCreator().build(videoFile);
} catch (RuntimeException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
Movie audio;
try {
audio = new MovieCreator().build(audioFile);
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (NullPointerException e) {
e.printStackTrace();
return false;
}
Track audioTrack = audio.getTracks().get(0);
video.addTrack(audioTrack);
Container out = new DefaultMp4Builder().build(video);
FileOutputStream fos;
try {
fos = new FileOutputStream(outputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
BufferedWritableFileByteChannel byteBufferByteChannel = new BufferedWritableFileByteChannel(fos);
try {
out.writeContainer(byteBufferByteChannel);
byteBufferByteChannel.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
private static class BufferedWritableFileByteChannel implements WritableByteChannel {
private static final int BUFFER_CAPACITY = 1000000;
private boolean isOpen = true;
private final OutputStream outputStream;
private final ByteBuffer byteBuffer;
private final byte[] rawBuffer = new byte[BUFFER_CAPACITY];
private BufferedWritableFileByteChannel(OutputStream outputStream) {
this.outputStream = outputStream;
this.byteBuffer = ByteBuffer.wrap(rawBuffer);
}
#Override
public int write(ByteBuffer inputBuffer) throws IOException {
int inputBytes = inputBuffer.remaining();
if (inputBytes > byteBuffer.remaining()) {
dumpToFile();
byteBuffer.clear();
if (inputBytes > byteBuffer.remaining()) {
throw new BufferOverflowException();
}
}
byteBuffer.put(inputBuffer);
return inputBytes;
}
#Override
public boolean isOpen() {
return isOpen;
}
#Override
public void close() throws IOException {
dumpToFile();
isOpen = false;
}
private void dumpToFile() {
try {
outputStream.write(rawBuffer, 0, byteBuffer.position());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Seem like this issue happens because Google devs have forgotten to handle that NullPointerException case. After several hours diving into the code base, I finally found the solution and It works very fine, you can try this:
Movie movie;
try{
movie = MovieCreator.build(videoPath);
}catch(NullPointerException e){
Log.d("AsyncTask", "Catch null getMovieBoxes");
FileDataSourceImpl fileDataSource = new FileDataSourceImpl(new File(videoPath));
IsoFile isoFile = new IsoFile(fileDataSource);
List<TrackBox> trackBoxes = isoFile.getBoxes(TrackBox.class);
for (TrackBox trackBox : trackBoxes) {
SchemeTypeBox schm = Path.getPath(trackBox, "mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schm[0]");
if (schm != null && (schm.getSchemeType().equals("cenc") || schm.getSchemeType().equals("cbc1"))) {
movie.addTrack(new CencMp4TrackImplImpl(fileDataSource.toString() + "[" + trackBox.getTrackHeaderBox().getTrackId() + "]", trackBox));
} else {
movie.addTrack(new Mp4TrackImpl(fileDataSource.toString() + "[" + trackBox.getTrackHeaderBox().getTrackId() + "]" , trackBox));
}
}
}

Problems creating PDF from stream

I am receiving a stream from the server. That stream represents a PDF, and I KNOW it is a pdf file. I am receiving it, and storing in the phone this way:
ResponseBody body=response.body();
File dir = new File(Environment.getExternalStorageDirectory() + “/myApp/“+variable+"/“+anotherVariable);
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, objetoFichero.get("nombre").getAsString());
try {
file.createNewFile();
FileOutputStream fos=new FileOutputStream(file);
InputStream is = body.byteStream();
int len = 0;
byte[] buffer = new byte[1024];
while((len = is.read(buffer)) != -1) {
fos.write(buffer,0,len);
}
fos.flush();
fos.close();
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
This way, the file is created, but using a file browser I try to open the pdf, and it opens, but it is blank.
Any idea about what I am doing wrong?
Thank you.
Assuming you have the document (the pdf) as a byteArray (documentBytes)
I would:
createUri(this, new File(getCacheDir(), "pdf/whateverNameYouWant.pdf"), documentBytes)
public static Uri createUri(#NonNull final Context context, final File name, #NonNull final byte[] data) throws IOException {
final File parent = name.getParentFile();
if (!parent.exists()) {
FileUtils.mkdirs(parent, null);
}
final OutputStream out = new FileOutputStream(name);
try {
out.write(data);
} finally {
StreamUtils.closeSilently(out);
}
return createUri(context, name);
}
public static void mkdirs(final File dir) {
if (!dir.mkdirs()) {
Log.w("File", "Failed to mkdirs: " + dir);
}
}
public static void closeSilently(#Nullable final Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (final Throwable ignore) {
}
}
}
You can then show the document with the uri received by createUri()

Retrofit 2 download image and save to folder

I need to download image from server and save it to folder, so I am using Retrofit 2.
Problem is that saved images is empty when I look for it in folder and I tried to debug and saw that Bitmap is null.
I do not get why, here is my code:
#GET("images/{userId}/{imageName}")
#Streaming
Call<ResponseBody> downloadImage(#Path("userId") String userId, #Path("imageName") String imageName);
Download image code:
private void downloadImage(final int position) {
String url = "htttp://myserver.com/";
retrofitImage = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
imageApi = retrofitImage.create(BlastApiService.class);
String userId = feedList.get(position).getUserId();
String fileName = feedList.get(position).getFile();
Call<ResponseBody> imageCall = imageApi.downloadImage(userId, fileName );
imageCall.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(response.isSuccess()){
String fileName = feedList.get(position).getFile();
InputStream is = response.body().byteStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
saveImage1(bitmap, fileName);
} else{
try {
Log.d("TAG", "response error: "+response.errorBody().string().toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("TAG", "Image download error: " + t.getLocalizedMessage());
}
});
}
Here is method to save image.
private void saveImage1(Bitmap imageToSave, String fileName) {
// get the path to sdcard
File sdcard = Environment.getExternalStorageDirectory();
// to this path add a new directory path
File dir = new File(sdcard.getAbsolutePath() + "/FOLDER_NAME/");
// create this directory if not already created
dir.mkdir();
// create the file in which we will write the contents
File file = new File(dir, fileName);
try {
FileOutputStream out = new FileOutputStream(file);
imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
counter++;
// if (counter < feedList.size()) {
//downloadImage(counter);
//} else {
setImage();
//}
} catch (Exception e) {
e.printStackTrace();
}
}
This worked for me:
public static boolean writeResponseBody(ResponseBody body, String path) {
try {
File file = new File(path);
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
//long fileSize = body.contentLength();
//long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(file);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
//fileSizeDownloaded += read;
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
after call this method you can get image from path:
boolean result = writeResponseBody(body, path);
if(result) {
Bitmap bitmap = BitmapFactory.decodeFile(path)
}
private boolean writeResponseBodyToDisk(ResponseBody body, String name) {
try {
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/MyApp";
File dir = new File(path);
if (!dir.exists())
dir.mkdirs();
File futureStudioIconFile = new File(path, name + ".pdf");//am saving pdf file
if (futureStudioIconFile.exists())
futureStudioIconFile.delete();
futureStudioIconFile.createNewFile();
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
}
outputStream.flush();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}

How to receive data from the server?

I am trying to fetchg data from server like MP3 files, video files, etc. in my application. The application should show the list of video files received from the server.
How can I do this?
/** this function will download content from the internet */
static int writeData(String fileurl, boolean append, String path,
String filename, Activity mContext) throws CustomException {
URL myfileurl = null;
ByteArrayBuffer baf = null;
HttpURLConnection conn = null;
String mimeType="";
final int length;
try {
myfileurl = new URL(fileurl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
conn = (HttpURLConnection) myfileurl
.openConnection();
conn.setDoInput(true);
conn.connect();
conn.setConnectTimeout(100000);
length = conn.getContentLength();
mimeType=conn.getContentType().toString();
System.out.println("Extension..."+mimeType);
if(mimeType.equalsIgnoreCase("application/vnd.adobe.adept+xml") || mimeType.equalsIgnoreCase("text/html; charset=utf-8"))
return 0;
if (length > 0) {
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
baf = new ByteArrayBuffer(1000);
int current = 0;
while ((current = bis.read()) != -1) {
try {
baf.append((byte) current);
mBufferError=false;
} catch (Exception e){
// TODO: handle exception
mBufferError=true;
e.printStackTrace();
throw new CustomException("### memory problem ", "Buffer Error");
}
}
}
} catch (IOException e) {
mBufferError=true;
e.printStackTrace();
}
try{
if(conn.getResponseCode()==200 && mBufferError==false)
{
path = path + "/" + filename;
boolean appendData = append;
FileOutputStream foutstream;
File file = new File(path);
boolean exist = false;
try {
if (appendData)
exist = file.exists();
else
exist = file.createNewFile();
} catch (IOException e) {
try {
return 1;
} catch (Exception err) {
Log.e("SAX", err.toString());
}
}
if (!appendData && !exist) {
} else if (appendData && !exist) {
} else {
try {
foutstream = new FileOutputStream(file, appendData);
foutstream.write(baf.toByteArray());
foutstream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}catch (Exception e) {
// TODO: handle exception
throw new CustomException("### I/O problem ", "I/O Error");
}
return 1;
}
once download complete search the file with extension(.3gp) for video
hope it helps
Check this link,
https://stackoverflow.com/search?q=how+to+download+mp3+%2Cvideos+from+server+in+android
Try this code
url = "your url name+filename.jpg,mp3,etc..."
FileName = "/sdcard/savefilename" // save in your sdcard
try{
java.io.BufferedInputStream in = new java.io.BufferedInputStream(new java.net.URL(url).openStream());
java.io.FileOutputStream fos = new java.io.FileOutputStream(FileName);
java.io.BufferedOutputStream bout = new BufferedOutputStream(fos,1024);
byte[] data = new byte[1024];
int x=0;
while((x=in.read(data,0,1024))>=0){
bout.write(data,0,x);
}
fos.flush();
bout.flush();
fos.close();
bout.close();
in.close();
}
catch (Exception ex)
{
}
and after you want to use MediaPlayer
and create object of mediaplayer in your activity
and play.
mp.reset();
mp.start();

Categories

Resources