How to Download Audio from URL using android - java

I'm new to android and for trainning i want to create an app that downloads audio from existing api.
i'm getting the link to downloading the file from the api, but i can't get it download properly
i've tried with download manager, in which, didn't even download it although it said it did.
here's the main code:
public void Download(String link)
{
downloadManager = (DownloadManager)m_context.getSystemService(m_context.DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse(link);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(false);
//Set the title of this download, to be displayed in notifications (if enabled).
request.setTitle("Downloading " + m_name);
//Set a description of this download, to be displayed in notifications (if enabled)
request.setDescription("Downloader");
//Set the local destination for the downloaded file to a path within the application's external files directory
request.setDestinationInExternalFilesDir(m_context, Environment.DIRECTORY_DOWNLOADS, m_name +".mp3");
//Enqueue a new download and same the referenceId
downloadReference = downloadManager.enqueue(request);
}
m_context is MainActivity
link is url that contains the file for downloading.
I'm using broadcast receiver to see if the download completed, and it did so i try to open it but nothing happens.
I've also tried to download it without the DownloadManager, even though it downloaded it, the size is very very small (1-15 kb) but sometimes(not most of the time maybe 5%) it gives me the complete audio(according to size and time)
here's the code:
public void Download(final String link)
{
try {
Thread t= new Thread(){
public void run() {
int count;
try {
URL url = new URL(link);
URLConnection conexion = url.openConnection();
Thread.sleep(20000);
conexion.connect();
// this will be useful so that you can show a tipical 0-100% progress bar
int lenghtOfFile = conexion.getContentLength();
// downlod the file
InputStream input = new BufferedInputStream(url.openStream());
String storageState = Environment.getExternalStorageState();
if (storageState.equals(Environment.MEDIA_MOUNTED)) {
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/Music",m_name+".mp3");
OutputStream output = new FileOutputStream(file);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}
} catch (Exception e) {
downloadSuccess = false;
e.printStackTrace();
}
}
};
t.start();
t.join();
} catch (InterruptedException e) {
downloadSuccess = false;
e.printStackTrace();
}
}
you will see thread.sleep, i've assumed that the response needs a little time to process but even a minute didn't finish.
Any guidance will be appreciated
Thank you
UPDATE:
There's something called GZIPInputStream that the encoding of the files that failed download correctly are in gzip
peace of code:
if ("gzip".equals(httpConn.getContentEncoding())) {
BufferedReader in= new BufferedReader(new InputStreamReader(new GZIPInputStream(httpConn.getInputStream())));
StringBuilder sb = new StringBuilder();
String read;
while ((read = in.readLine()) != null){
sb.append(read);
}
}
it's still not helping me to download in the correct way but i think it's the right path, and again any help will be great. thank you

Related

Download File from Direct Download URL

I'm trying to download the following the following file, with this link that redirects you to a direct download: http://www.lavozdegalicia.es/sitemap_sections.xml.gz
I've done my own research, but all the results I see are related to HTTP URL redirections
[3xx] and not to direct download redirections (maybe I'm using the wrong terms to do the research).
I've tried the following pieces of code (cite: https://programmerclick.com/article/7719159084/ ):
// Using Java IO
private static void downloadFileFromUrlWithJavaIO(String fileName, String fileUrl) {
BufferedInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
URL url = new URL(fileUrl);
inputStream = new BufferedInputStream(url.openStream());
outputStream = new FileOutputStream(fileName);
byte data[] = new byte[1024];
int count;
while ((count = inputStream.read(data, 0, 1024)) != -1) {
outputStream.write(data, 0, count);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Using Apache common IO
private static void downloadFileFromUrlWithCommonsIO(String fileName, String fileUrl) {
try {
FileUtils.copyURLToFile(new URL(fileUrl), new File(fileName));
} catch (IOException e) {
e.printStackTrace();
}
}
// Using NIO
private static void downloadFileFromURLUsingNIO(String fileName, String fileUrl) {
try {
URL url = new URL(fileUrl);
ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(fileName);
fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
fileOutputStream.close();
readableByteChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
But the result I get with any of the three options is an empty file, my thoughts are that the problem is related to the file being a .xml.gz because when I debug it the inputStream doesn't seem to have any content.
I ran out of options, anyone has an idea of how to handle this case, or what would be the correct terms I should use to research about this specific case?
I found a solution, there's probably a more polite way of achieving the same result but this worked fine for me:
//Download the file and decompress it
filecount=0;
URL compressedSitemap = new URL(urlString);
HttpURLConnection con = (HttpURLConnection) compressedSitemap.openConnection();
con.setRequestMethod("GET");
if (con.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP || con.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM) {
String location = con.getHeaderField("Location");
URL newUrl = new URL(location);
con = (HttpURLConnection) newUrl.openConnection();
}
String file = "/home/user/Documentos/Decompression/decompressed" + filecount + ".xml";
GZIPInputStream gzipInputStream = new GZIPInputStream(con.getInputStream());
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len = 0;
while ((len = gzipInputStream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
filecount++;
Two things to note:
When I was trying to do HTTPGet the url that was a redirect, the response code was 301 or 302 (depending on the example I used), I overcame this problem with the if check, that follows the redirect and aims to the downloaded file.
Once aiming the file, to get the content of the compressed file I found the GZIPInputStream package, that allowed me to get an inputStream directly from the compressed file and dump it on an xml file, that saved me the time of doing it on three steps (decompress, read, copy).

Wrong Mime-Type when downloading binary file on mobile data (Android)

I'm trying to download a binary file using:
URL url = new URL(urlStr);
HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
ucon.connect();
InputStream is = new BufferedInputStream(ucon.getInputStream());
When run via mobile data (on Samsung Galaxy 4, Android 5.0.1) I receive the following response
j���UFEHLER��6ERROR��`Заявеното съдържание не може да бъде заредено ��&Wrong MIME-Type���Fback��2
Which means "The content requested cannot be loaded" in Bulgarian (the server I download from is Bulgaria). But more informative seems "Wrong MIME-Type" at the end of the response.
I tried the same using HttpGet with no result.
The weird thing is everything is ok when I execute the same request via Wifi.
Also I can download the file from the brower on mobile data, but not for the code. Also I've tested on Lenovo with Android 4.4.2 via mobile data and is also worked.
I noticed I'm getting Content-Type: application/vnd.wap.wmlc (logged ucon.getResponseCode()) when connected via mobile data and nothing set as content type when via WiFi.
Any ideas? :/
Here's my working code for file downloading. You can have a look to check if you're missing something.
public class ImageDownloaderAsyncTask extends
AsyncTask<Void, Integer, Integer> {
private static File f;
protected void doInBackground() throws IOException {
File dir = new File(Constants.FILE_PATH);
if (!dir.exists()) dir.mkdir();
f = new File(Constants.FILE_PATH + Constants.FILE_NAME);
if (f != null && !f.exists()) {
f.createNewFile();
}
try {
URL url = new URL(fileUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
String data1 = f.getPath();
FileOutputStream stream = new FileOutputStream(data1);
byte data[] = new byte[4096];
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled()) {
input.close();
}
stream.write(data, 0, count);
}
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected Integer doInBackground(Void... params) {
try {
doInBackground();
} catch (IOException e) {
e.printStackTrace();
}
return 1;
}
protected void onPostExecute(Integer result) {}
}

android downloading multiple files with InputStream FileOutputStream

So I have an app which downloads certain files, dedicated to a client of mine who is hosting his files on a remote location, and i'm doing so using the code below:
public class DownloadService extends IntentService {
private int result = Activity.RESULT_CANCELED;
public DownloadService() {
super("DownloadService");
}
#Override
protected void onHandleIntent(Intent intent) {
String urlPath = intent.getStringExtra(URL);
String fileName = intent.getStringExtra(FILENAME);
File output = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
fileName);
if (output.exists()) {
output.delete();
}
URLConnection streamConnection = null;
InputStream stream = null;
FileOutputStream fos = null;
try {
URL url = new URL(urlPath);
streamConnection = url.openConnection();
stream = streamConnection.getInputStream();
streamConnection.connect();
long lengthofFile = streamConnection.getContentLength();
InputStream reader = stream;
bis = new BufferedInputStream(reader);
fos = new FileOutputStream(output.getPath());
int next = -1;
int progress = 0;
int bytesRead = 0;
byte buffer[] = new byte[1024];
while ((bytesRead = bis.read(buffer)) > 0) {
fos.write(buffer, 0, bytesRead);
progress += bytesRead;
int progressUpdate = (int)((progress * 100) / lengthofFile);
Intent testIntent = new Intent(".MESSAGE_INTENT");
testIntent.putExtra(PERCENTAGE, progressUpdate);
sendBroadcast(testIntent);
}
result = Activity.RESULT_OK;
fos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
publishResults(output.getAbsolutePath(), result);
}
private void publishResults(String outputPath, int result) {
Intent intent = new Intent(".MESSAGE_INTENT");
intent.putExtra(FILEPATH, outputPath);
intent.putExtra(RESULT, result);
sendBroadcast(intent);
}
}
and to call this service i would use:
Intent intent = new Intent(MainActivity.getAppContext(), DownloadService.class);
intent.putExtra(DownloadService.FILENAME, downloadFileName[item]);
intent.putExtra(DownloadService.URL, urlDownload[item]);
MainActivity.getAppContext().startService(intent);
now this allows user to download one file at a time, however if the user downloads another file, the second file will have to wait till the first file is done downloading.
now what is happening in my case is:
1- First download FILE_1 is downloading, and in the status is says FILE_1.
2- User clicks a new file download, the status changes the first file name to the second file name, and waits till FILE_1 finishes download to start with FILE_2 however the active download is changed from FILE_1 to FILE_2.
questions:
is there a way to call DownloadService multiple times for multiple files?
is it possible to fix the problem i'm facing? treating download intent services as two different intents?
UPDATE
I managed to solve this issue by assigning a unique Int ID per file, each ID will point to a position in the listview which displays the files being downloaded or queued, then i work with each file on it's own.
Following code uses commons-io-2.4.jar library to make your work easy by handling low level data movements as you would focus on method in hand
URL someUrl = new URL("your url String"); //
File someFile = new File("your file, where you want to save the data");
FileUtils.copyURLToFile(someUrl, someFile );
if you want to call this statement few time to download different files from the server following code might give you an idea what you might want to do, but you will have to write it's equivalent code to run in android which you want to probably AsyncTask
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.io.FileUtils;
public class DownloadTest {
public static void main(String[] args) {
Thread thread = new Thread(){
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
dowanloadFile(new URL("some url"), new File("some file"));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
thread.start();
}
private static void dowanloadFile(URL url, File file){
try {
FileUtils.copyURLToFile(url, file );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

PlayFramework. How to upload a photo using an external endpoint?

How do I upload a photo using a URL in the playframework?
I was thinking like this:
URL url = new URL("http://www.google.ru/intl/en_com/images/logo_plain.png");
BufferedImage img = ImageIO.read(url);
File newFile = new File("google.png");
ImageIO.write(img, "png", newFile);
But maybe there's another way. In the end I have to get the File and file name.
Example controller:
public static Result uploadPhoto(String urlPhoto){
Url url = new Url(urlPhoto); //doSomething
//get a picture and write to a temporary file
File tempPhoto = myUploadPhoto;
uploadFile(tempPhoto); // Here we make a copy of the file and save it to the file system.
return ok('something');
}
To get that photo you can use The play WS API, the code behind is an example extracted from the play docs in the section Processing large responses, I recommend you to read the full docs here
final Promise<File> filePromise = WS.url(url).get().map(
new Function<WSResponse, File>() {
public File apply(WSResponse response) throws Throwable {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = response.getBodyAsStream();
// write the inputStream to a File
final File file = new File("/tmp/response.txt");
outputStream = new FileOutputStream(file);
int read = 0;
byte[] buffer = new byte[1024];
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
return file;
} catch (IOException e) {
throw e;
} finally {
if (inputStream != null) {inputStream.close();}
if (outputStream != null) {outputStream.close();}
}
}
}
);
Where url is :
String url = "http://www.google.ru/intl/en_com/images/logo_plain.png"
This is as suggested in play documentation for large files:
*
When you are downloading a large file or document, WS allows you to
get the response body as an InputStream so you can process the data
without loading the entire content into memory at once.
*
Pretty much the same as the above answer then some...
Route: POST /testFile 'location of your controller goes here'
Request body content: {"url":"http://www.google.ru/intl/en_com/images/logo_plain.png"}
Controller(using code from JavaWS Processing large responses):
public static Promise<Result> saveFile() {
//you send the url in the request body in order to avoid complications with encoding
final JsonNode body = request().body().asJson();
// use new URL() to validate... not including it for brevity
final String url = body.get("url").asText();
//this one's copy/paste from Play Framework's docs
final Promise<File> filePromise = WS.url(url).get().map(response -> {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = response.getBodyAsStream();
final File file = new File("/temp/image");
outputStream = new FileOutputStream(file);
int read = 0;
byte[] buffer = new byte[1024];
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
return file;
} catch (IOException e) {
throw e;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}); // copy/paste ended
return filePromise.map(file -> (Result) ok(file.getName() + " saved!")).recover(
t -> (Result) internalServerError("error -> " + t.getMessage()));
}
And that's it...
In order to serve the file after the upload phase you can use this answer(I swear I'm not promoting myself...): static asset serving from absolute path in play framework 2.3.x

Save mp3 from HTTP server with BlackBerry JDE 4.5.0 and play file

Apologies, I am very new to BlackBerry development. All I need to do is save an mp3 file (which I download from a HTTP server), and then play it back. I have most of the code done, but I keep getting a file system error 1003. (I have to use BlackBerry JDE 4.5.0).
try {
FileConnection fconn = (FileConnection) Connector.open( "file://data/myfile.mp3", Connector.READ_WRITE );
final HttpConnection connection = (HttpConnection) Connector.open("http://som.server.com/andFile.mp3;interface=wifi");
if (!fconn.exists()) {
fconn.create();
} else {
fconn.delete();
fconn = (FileConnection) Connector.open( "file://data/myfile.mp3", Connector.READ_WRITE );
fconn.create();
}
final InputStream inputStream = connection.openInputStream();
final StringBuffer buffer = new StringBuffer();
try {
int ch;
while ( ( ch = inputStream.read() ) != -1 ) {
buffer.append( (char) ch );
} finally {
inputStream.close();
connection.close();
}
fconn.setWritable(true);
final OutputStream outputStream = fconn.openOutputStream();
outputStream.write(buffer.toString().getBytes());
outputStream.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
final Player mPlayer;
final VolumeControl vc;
final InputStream is = getClass().getResourceAsStream("data/myfile.mp3");
try {
mPlayer = Manager.createPlayer(is, "audio/mpeg");
mPlayer.addPlayerListener(WelcomeScreen.this);
mPlayer.realize();
mPlayer.prefetch();
vc = (VolumeControl) mPlayer.getControl("VolumeControl");
vc.setLevel(50);
mPlayer.start();
} catch (Exception e) {
System.out.println(e.getMessage());
}
In the above code I just try to play the file I save, but it I get the file system error. I did check on the device, and it seems that the file was actually properly saved once.
What is the correct path that I should use to save files under the application data folder?
Check this article
There is explained how to compose file path for files you want to save to device memory or memory sd card.

Categories

Resources