Android downloading files - Issues with Stream that is not complete yet - android

Im downloading files from a server, some big, some small.
protected Long doInBackground(Object... params) {
Context context = (Context) params[0];
String name = (String) params[1];
String urlString = (String) params[2];
File mediadir = context.getDir("tvr", Context.MODE_PRIVATE);
try {
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
connection.connect();
int lenghtOfFile = connection.getContentLength();
InputStream is = url.openStream();
Log.d("DOWNLOAD NAME",name);
File new_file = new File(mediadir, name);
FileOutputStream fos = new FileOutputStream(new_file.getPath());
byte data[] = new byte[1024];
int count = 0;
long total = 0;
int progress = 0;
while ((count=is.read(data)) != -1){
total += count;
int progress_temp = (int)total*100/lenghtOfFile;
if(progress_temp%10 == 0 && progress != progress_temp){
progress = progress_temp;
}
fos.write(data, 0, count);
}
is.close();
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e("DOWNLOAD ERROR", e.toString());
}
return null;
}
As I now understand it, Im downloading the file via a stream and streaming the data into a file. So in effect the file is created since the first byte of data.
Now, on the other end of things Im playing files from my internal directory by looking for files in a directory and then playing them:
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setDisplay(holder);
FileInputStream fileInputStream = new FileInputStream(path);
mediaPlayer.setDataSource(fileInputStream.getFD());
fileInputStream.close();
mediaPlayer.prepare();
mediaPlayer.start();
Now this issue is that the file will be played even though its not fully downloaded!
Is this true? If so, how must I check if the file is complete before trying to play it?

Yes, this is a valid scenario, as in many cases your download speed will be slower than the reading and playing speed of the MediaPlayer.
Seeing as you're using an AsyncTask, you can fix this problem by calling the playing code in the onPostExecute() method, as that only runs after all work in the doInBackground() method has completed.

Related

Image URL to File Object

I'm trying to convert this image url to file object :
https://graph.facebook.com/v4.0/10211842143528384/picture?height=200&width=200&migration_overrides=%7Boctober_2012%3Atrue%7D
this link came from the facebook response after i logged in.
i used this method to convert this image url to File object:
URL url = null;
try {
url = new URL(sharePreferences.getPreferencesProfilePicture());
} catch (MalformedURLException e) {
e.printStackTrace();
}
File f = new File(url.getFile());
Log.d("CHECKER",""+f.exists());
Log.d("CHECKER",""+f.length());
but when i check it's length, its just 0 and the file exist is false.
You have a file with length 0 because you are just creating it with the name of the result of url.getFile(), url.getFile() returns a string which corresponds to the fetched file name.So you end up with a file named picture:
https://graph.facebook.com/v4.0/10211842143528384/picture?height=200&width=200&migration_overrides=%7Boctober_2012%3Atrue%7 But what about the contents? you have to download them fron the internet as a stream and feed that stream into a file. There many ways of doing that with plain Java. A basic copy-paste from https://www.baeldung.com/java-download-file
try (BufferedInputStream in = new BufferedInputStream(new URL(FILE_URL).openStream());
FileOutputStream fileOutputStream new FileOutputStream(FILE_NAME)) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
} catch (IOException e) {
// handle exception
}
Since you are using android I would strongly encourage you to use fully featured Network libraries such as OkHttp3, Retrofit or Volley, but guessing your knowledge I think you will do better learning the basics on Java then jump to the mentioned libraries.
Remember, for android you need the INTERNET permission to access the internet, then if you download into a file on the external storage you would also need the EXTERNAL_STORAGE permission. Snippet for android:
try {
URLConnection conection = url.openConnection();
conection.connect();
int lenghtOfFile = conection.getContentLength();
// Read from the Network stream
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/downloaded.png");
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
total += count;
// Feed the bytes read from the input stream into our output stream
output.write(data, 0, count);
}
// Flushing the out stream.
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
This snippet does networking stuff so you need to run it on a background thread. I hope my answer helps you, if not, let me know what else can I do for you.

The best way to download and pause ,resume a big file in android? [duplicate]

This question already has answers here:
Download a file with Android, and showing the progress in a ProgressDialog
(16 answers)
Closed 5 years ago.
I need to download a big file on my app (almost 1gb) and i was wondering what is the best way to do that and some libs to help me. First I looked the Android Asynchronous Http Library but I didn't find examples showing how to publish the progress or start, pause download. Then I don't know if should I use this lib or just use a standart http commons. Other problem is, should I use a service to download my file??
You can use this code in asynctask to download with resume:
#SuppressLint("Wakelock")
#Override
protected String doInBackground(String... sUrl) {
// take CPU lock to prevent CPU from going off if the user
// presses the power button during download
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
wl.acquire();
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
File SDCardRoot = Environment.getExternalStorageDirectory();
File file = new File(SDCardRoot,FOLDER_PATH1+FOLDER_PATH2+ "/"+fileName);
int downloaded=0;
if(file.exists()){
downloaded=(int) file.length();
connection.setRequestProperty("Range", "bytes=" + (int) file.length() + "-");
}
else{
file.createNewFile();
}
connection.setDoInput(true);
connection.setDoOutput(true);
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength()+(int)file.length();
// download the file
input = connection.getInputStream();
if(downloaded>0){
output = new FileOutputStream(file,true);
}
else{
output = new FileOutputStream(file);
}
byte data[] = new byte[1024];
long total = downloaded;
int count;
mProgressDialog.setMax(fileLength/1024);
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled())
return null;
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int)total/1024);
output.write(data, 0, count);
}
output.flush();
if (output != null)
output.close();
if (input != null)
input.close();
if (connection != null)
connection.disconnect();
wl.release();
return null;
} catch (Exception e) {
return e.toString();
}
}
catch (Exception e) {
return e.toString();
}
}
You should use library because it will handle your all test cases & it will help you to maintain downloading state.
Some of libraries:
1] ThinDownloadManager
2] Android-Download-Manager-Pro
You should use DownLoad Manager which is a system service that can handle long-running HTTP downloads.

InputStream Exception while downloading a file

I am trying to download a PPT file from a server.
it's in Bytes.
but while debugging I noticed that the input stream throws an exception of FileNotFound while running.. the file does exist on the server, here's my code, any help would be greatly appreciated.
public class DownloadFileAsync extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... aurl) {
int count;
try {
URL url = new URL(aurl[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("Authorization", "Basic " + SharedPref.getAuthPrefValue());
connection.addRequestProperty("Device", BaseApplication.getCurrentDevice().getDevice().toString());
connection.addRequestProperty("DeviceId", BaseApplication.getCurrentDevice().getDeviceId());
connection.connect();
int lengthOfFile = connection.getContentLength();
Log.d("ANDRO_ASYNC", "Length of file: " + lengthOfFile);
InputStream input = new BufferedInputStream(url.openStream());
File sdcardDest = new File(Environment.getExternalStorageDirectory(), "Availo");
String finalDest = sdcardDest + File.separator + "Check1" + "." + "PPT";
OutputStream output = new FileOutputStream(finalDest);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lengthOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I am using Charles on Mac (which is similar to fiddler on windows.) to see what I send and receive from the server,
The server doesn't return any error, though it shows download steps for 6-7 sec, downloading around 400 bytes and then it stops.
The Exception is thrown from the input stream line.
Thanks!
I suggest you take a look at the DownloadManager system service. it's designed specifically for what you are trying to do:
(from the documentation)
The download manager is a system service that handles long-running
HTTP downloads. Clients may request that a URI be downloaded to a
particular destination file. The download manager will conduct the
download in the background, taking care of HTTP interactions and
retrying downloads after failures or across connectivity changes and
system reboots
While I do agree with Muzikant regarding the download manager,
FileNotFoundException is usually thrown when... the file is not found on the local device...
You need to do the following to make sure it doesnt happen
File dest = new File(finalDest);
try{
File parentDest = dest.getParentFile();
if(!parentDest.exists()){
parentDest.mkdirs(); //make all the directory structures needed
}
if(!dest.exists()){
dest.createNewFile();
}
OutputStream output = new FileOutputStream(dest);
//now you can use your file dest
//write data to it...
}catch (Exception e){
}

Cache of Videos

I am trying to cache of videos by this
try {
URL oracle = new URL(url);
URLConnection yc = oracle.openConnection();
InputStream in = yc.getInputStream();
File file = new File(getApplicationContext().getCacheDir() ,url);
if(!file.exists()){
file.setReadable(true);
file.createNewFile();
if (file.canWrite()){
FileOutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 ) {
out.write(buffer,0, len1);
}
out.close();
}
in.close();
Runtime.getRuntime().exec("chmod 755 "+getCacheDir() +"/"+ url);
videoView.setVideoPath("chmod 755 "+getCacheDir() +"/"+ url);
}else {
videoView.setVideoURI(Uri.parse(videoUrl));
}
} catch (Exception e) {
// TODO: handle exception
}
videoView.setVideoURI(Uri.parse(videoUrl));
MediaController mc = new MediaController(VideoViewC.this);
videoView.setMediaController(mc);
videoView.requestFocus();
videoView.start();
mc.show();
But I found Error java.net.SocketException: Connection reset by peer.
if you have any suggestion please give me.
I have my case problem, and it consisted in particular the my http server, which if not properly authenticate just closed the client connection, it is my Ask:
android-async-http Status code and response to onFailure
Maybe you have it too, due to the peculiarities of your httpservers
Did you implement caching video files?

I want to download an audio from the server

private void doFileDownload() throws Exception {
BufferedInputStream in = null;
BufferedOutputStream out = null;
String url = "http://www.jimsonmok.com/server/uploads/"; //input
String file = "/sdcard/Shek Kip Mei MTR Station Exit A.3gp"; //output
try{
url += URLEncoder.encode("Shek Kip Mei MTR Station Exit A.3gp");
URL download = new URL(url);
URLConnection downloadConnection = download.openConnection(); //set up connection
in = new BufferedInputStream(downloadConnection.getInputStream());
out = new BufferedOutputStream(new FileOutputStream(file));
int contentlength = downloadConnection.getContentLength(); //getting the length of the file
for(int counter=0;counter < contentlength;counter++) //storing the binary I/O file
out.write(in.read());
}catch(IOException e){
}
in.close();
out.close();
}
I am trying to download an audio from the server using an android phone.
The code above I am using does not work in android.
Does anyone know the reasons?
Thanks a lot!

Categories

Resources