Android - Download and Open Pdf - android

I have a application that downloads and opens a pdf from a listview click listener.
A file downloads and save to my phone but it has a file size of 0 bytes therefore It can not open. I Used tutorial code from http://www.coderzheaven.com/2013/03/06/download-pdf-file-open-android-installed-pdf-reader/ Here is my code. Any help will be greatly appreciated.
public class OpenPdfActivity extends Activity {
TextView tv_loading;
String dest_file_path = "pdf-test.pdf";
int downloadedSize = 0, totalsize;
String download_file_url = "http://www.education.gov.yk.ca/pdf/pdf-test.pdf";
float per = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv_loading = new TextView(this);
setContentView(tv_loading);
tv_loading.setGravity(Gravity.CENTER);
tv_loading.setTypeface(null, Typeface.BOLD);
downloadAndOpenPDF();
}
void downloadAndOpenPDF() {
new Thread(new Runnable() {
public void run() {
Uri path = Uri.fromFile(downloadFile(download_file_url));
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
} catch (ActivityNotFoundException e) {
tv_loading
.setError("PDF Reader application is not installed in your device");
}
}
}).start();
}
File downloadFile(String dwnload_file_path) {
File file = null;
try {
URL url = new URL(dwnload_file_path);
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
// connect
urlConnection.connect();
// set the path where we want to save the file
File SDCardRoot = Environment.getExternalStorageDirectory();
// create a new file, to save the downloaded file
file = new File(SDCardRoot, dest_file_path);
FileOutputStream fileOutput = new FileOutputStream(file);
// Stream used for reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
// this is the total size of the file which we are
// downloading
totalsize = urlConnection.getContentLength();
setText("Starting PDF download...");
// create a buffer...
byte[] buffer = new byte[1024 * 1024];
int bufferLength = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
per = ((float) downloadedSize / totalsize) * 100;
setText("Total PDF File size : "
+ (totalsize / 1024)
+ " KB\n\nDownloading PDF " + (int) per
+ "% complete");
}
// close the output stream when complete //
fileOutput.close();
setText("Download Complete. Open PDF Application installed in the device.");
} catch (final MalformedURLException e) {
setTextError("Some error occured. Press back and try again.",
Color.RED);
} catch (final IOException e) {
setTextError("Some error occured. Press back and try again.",
Color.RED);
} catch (final Exception e) {
setTextError(
"Failed to download image. Please check your internet connection.",
Color.RED);
}
return file;
}
void setTextError(final String message, final int color) {
runOnUiThread(new Runnable() {
public void run() {
tv_loading.setTextColor(color);
tv_loading.setText(message);
}
});
}
void setText(final String txt) {
runOnUiThread(new Runnable() {
public void run() {
tv_loading.setText(txt);
}
});
}
}

A couple of things:
Maybe add a timeout?
Try to NOT check the content length for now.
Use BufferedOutputStream
Something like this:
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream out = new BufferedOutputStream( fos);
try {
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout( 15000);
urlConnection.connect();
try {
InputStream in = urlConnection.getInputStream();
byte[] buffer = new byte[1024 * 1024];
int len = 0;
while (( len = in.read( buffer)) > 0)
{
out.write( buffer, 0, len);
}
out.flush();
} finally {
fos.getFD(). sync();
out.close();
}
} catch (IOException eio) {
Log.e("Download Tag", "Exception in download", eio);
}

(Including the logcat may help to have a better idea of what's going on)
One possible issue is this :
fileOutput.close();
don't ensure that all bytes are written to the disk. If you try to read the file immediately after closing the stream, it's possible that the file is not totally written yet (especially because your buffer is big).
The solution is to request a sync after the close():
fileOutput.close();
fileOutput.getFD().sync();
similar question here

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

load pdf from url in android

I have to display pdf file in webview using this link
https://col1.3yd.co:8087/api/getDoc?username=test&password=12345678&doc_id=dc_1
The problem is when i open this link in webview using online google docs viewer, then i am getting error "Whoops!! There was a problem displaying this image."
https://docs.google.com/gview?embedded=true&url=https://col1.3yd.co:8087/api/getDoc?username=test&password=12345678&doc_id=dc_1
After trying too many methods from stackoverflower I am using this code to load pdf file.
The problem is each time file is downloading and its taking time. Is there any other way to display file in webview.
private void downloadAndOpenPDF(){
progressDialog = new DLProgressDialog(context);
progressDialog.show();
new Thread(new Runnable() {
public void run() {
Uri path = Uri.fromFile(downloadFile(download_file_url));
try {
if(progressDialog.isShowing()) {
progressDialog.dismiss();
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
} catch (ActivityNotFoundException e) {
}
}
}).start();
}
private File downloadFile(String dwnload_file_path) {
File file = null;
try {
URL url = new URL(dwnload_file_path);
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
// connect
urlConnection.connect();
// set the path where we want to save the file
File SDCardRoot = Environment.getExternalStorageDirectory();
// create a new file, to save the downloaded file
file = new File(SDCardRoot, dest_file_path);
FileOutputStream fileOutput = new FileOutputStream(file);
// Stream used for reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
// this is the total size of the file which we are
// downloading
totalsize = urlConnection.getContentLength();
// create a buffer...
byte[] buffer = new byte[1024 * 1024];
int bufferLength = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
per = ((float) downloadedSize / totalsize) * 100;
}
// close the output stream when complete //
fileOutput.close();
} catch (final MalformedURLException e) {
} catch (final IOException e) {
} catch (final Exception e) {
}
return file;
}

InputStream returns empty file when downloading a PDF

So I'm trying to download a PDF file using HttpURLConnection and I think I've done everything right with the input- and outputstreams, yet when I open the downloaded PDF file (using the built in File Manager in Android and/or ADB), or just inspect it by transferring it to OS X, it's completely empty and the size shows 0 bytes.
The site I'm trying to download the PDF from is:
http://www.pdf995.com/samples/pdf.pdf
Here's my code
public static void DownloadFile(final String fileURL, final File directory) {
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
try {
FileOutputStream f = new FileOutputStream(directory);
URL u = new URL(fileURL);
c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
//c.setRequestProperty("Content-Type", "application/pdf");
//c.setDoOutput(true);
c.connect();
Log.d("debugz", Integer.toString(c.getContentLength()));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.flush();
f.getFD().sync();
f.close();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
public static String getPDF(String pdfurl) {
String extStorageDirectory = Environment.getExternalStorageDirectory()
.toString();
File folder = new File(extStorageDirectory, "schematisktscheman");
folder.mkdir();
File file = new File(folder, "schemainfo.pdf");
try {
file.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
DownloadFile(pdfurl, file);
return null; //added return
}
In my main activity:
SchedulePdfProcessor.getPDF("http://www.pdf995.com/samples/pdf.pdf");
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory() + "/schematisktscheman/schemainfo.pdf")));
EDIT: I ran the network code on the main thread, which threw an exception. Now creating a new thread for the downloading and it gets the example PDF (http://www.pdf995.com/samples/pdf.pdf) and puts its content in the file all fine.
Thanks to #greenapps!
First, replace:
f.close();
with:
f.flush();
f.getFD().sync();
f.close();
This ensures everything is written to disk before continuing.
Then, you need to use MediaScannerConnection and scanFile() to get the MediaStore to know about the updated file.
I ran the network code on the main thread, which threw an exception. Now creating a new thread for the downloading and it gets the example PDF (http://www.pdf995.com/samples/pdf.pdf) and puts its content in the file all fine.
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
try {
FileOutputStream f = new FileOutputStream(directory);
URL u = new URL(fileURL);
c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
//c.setRequestProperty("Content-Type", "application/pdf");
//c.setDoOutput(true);
c.connect();
Log.d("debugz", Integer.toString(c.getContentLength()));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.flush();
f.getFD().sync();
f.close();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();

android download large file

i have various files need to download from web into phone
I have done the code but the code only can let me download with the small size such as picture/photo. A large file like .apk which cost around 2mb to >100mb will failed me.
below is the code:
final ProgressDialog progress=ProgressDialog.show(this, "Please wait", "Loading ...", true);
new Thread()
{
public void run()
{
try {
URL url = new URL("http://www.domain.com/apk/Gmail.apk");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
File SDCardRoot = Environment.getExternalStorageDirectory();
File file = new File(SDCardRoot, "Gmail.apk");
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
//downloadedSize += bufferLength;
}
fileOutput.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
progress.dismiss();
}
}.start();

Program freezes while download a file in android

I am getting MalformedURLexception in the following code, and i have no idea, whats causing it.
public void down(String url)
{ try {
URL url1 = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) url1.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
File SDCardRoot = Environment.getExternalStorageDirectory();
//create a new file, specifying the path, and the filename
//which we want to save the file as.
File file = new File(SDCardRoot,"somefile.ext");
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
//add up the size so we know how much is downloaded
downloadedSize += bufferLength;
//report progress
}
fileOutput.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
It says unknown protocol.
The connection is totally fine unti the reading part comes up,
before that the code is even printing right size of the file.
Also the file i am trying to download has a url like
http://download12.aomethin.com/blaa-blaa
If i try to add www, the request starts redirecting.
Although i think this might be a noobish but I also want to know how to get the name of this file and save file with that name instead of the one i choose.
Edit: the program is working now i just need to know how do i get the right name of the file. And make this a background process.
downloading on the main thread is not a good practice; you should implement it on a new thread; because while downloading, the main thread is busy for downloading the file. If the waiting time be more than expected the system will generate "Not responding" error.
In order to do that you can use "TaskAsync" or "IntentService" or even making a new thread. though, I suggest [TaskAsync] as it is easy to implement.
here is a good practice to set the file name yourself:
public void downloadClicked() {
InputStream in = null;
FileOutputStream f = null;
try {
String path ="ftp://administrator:password#131.164.140.118:21/MyShedule.zip";
String targetFileName = "MyShedule.zip";
URL u = new URL(path);
URLConnection c = u.openConnection();
c.setDoOutput(true);
c.connect();
String string = Environment.getExternalStorageDirectory().getPath().toString();
in = c.getInputStream();
f = new FileOutputStream(new File(string +"/kidsLibrary/"+ targetFileName));
IOUtils.copy(in, f);
} catch (MalformedURLException e) {
Toast.makeText(KidsLibrary.this, e.toString(), Toast.LENGTH_LONG)
.show();
} catch (ProtocolException e) {
Toast.makeText(KidsLibrary.this, e.toString(), Toast.LENGTH_LONG)
.show();
} catch (FileNotFoundException e) {
Toast.makeText(KidsLibrary.this, e.toString(), Toast.LENGTH_LONG)
.show();
} catch (IOException e) {
Toast.makeText(KidsLibrary.this, e.toString(), Toast.LENGTH_LONG)
.show();
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(f);
}
}

Categories

Resources