I am an iOS developer but have been tasked with updating our company's android apps also (so I have little android experience) The android app currently loads PDFs from raw and then displays them in another pdf reader application also installed on the android... however I would like to instead get the pdf's from the internet.
this is the code being using to show the pdf stored locally.
if (mExternalStorageAvailable==true && mExternalStorageWriteable==true)
{
// Create a path where we will place our private file on external
// storage.
Context context1 = getApplicationContext();
File file = new File(context1.getExternalFilesDir(null).toString() + "/pdf.pdf");
URL url = new URL("https://myurl/pdf.pdf");
URLConnection urlConnection = url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
OutputStream os = new FileOutputStream(file);
try {
byte[] data = new byte[in.available()];
in.read(data);
os.write(data);
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
} catch (IOException e) {
// Unable to create file, likely because external storage is
// not currently mounted.
Log.w("ExternalStorage", "Error writing " + file, e);
Context context2 = getApplicationContext();
CharSequence text1 = "PDF File NOT Saved";
int duration1 = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context2, text1, duration1);
toast.show();
} finally {
in.close();
os.close();
}
}
Eventually the pdf's will come from a website and the website will require an HTML post request sent to it before the PDF can be downloaded. I think I will be able to figure out the HTML post, but for now how can I download a PDF from the internet and have it display. I tried changing the URI to point to the location but that didn't work, or I structured it incorrectly.
Also keep in mind for security reasons I do not want to display this using google viewer and a webview
You just need to read from a distant server. I'd try something like:
URL url = new URL("http://www.mydomain.com/slug");
URLConnection urlConnection = url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
try {
readStream(in); // Process your pdf
} finally {
in.close();
}
You may also want to checkout the AndroidHttpClient class to make http requests directly (GET or POST in your application).
Related
I am able to download and view from url ending with *.pdf with the below code
private static final int MEGABYTE = 1024 * 1024;
public static void downloadFile(String fileUrl, File directory){
try {
URL url = new URL(fileUrl);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
//urlConnection.setRequestMethod("GET");
//urlConnection.setDoOutput(true);
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(directory);
int totalSize = urlConnection.getContentLength();
byte[] buffer = new byte[MEGABYTE];
int bufferLength = 0;
while((bufferLength = inputStream.read(buffer))>0 ){
fileOutputStream.write(buffer, 0, bufferLength);
}
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
but I have tried to download PDF file with url ending with .aspx as its generate PDF dynamically and its not working .
I have also tried to embed with webview with google doc url "http://docs.google.com/viewer?url="+URL but its also not working.
Can anyone help in this?
'.aspx' Is ASP.NET page that is actually web form.
Web forms are contained in files with a ".aspx" extension; these files
typically contain static (X)HTML markup or component markup.
So what you are loading is a simple HTML page rendered on server side. So you cannot use it to view PDF - in PDF viewer.
Instead of openning '.aspx' from file load this url into WebView - this will work only if there are no additional security on the site you are pointing to.
In case of Google Docs the link you are providing to the WebView should be sharing links like following:
https://drive.google.com/file/d/xx-xxxxxxxxxxxxxxx/view?usp=sharing
Where x's are part of hash. To get this link - click on Share option for the document and then get shareable link.
Before WebView reaches pdf document it could receive few redirects that potentially will be handled by Android itself. To avoid this you need to override WebViewClient#shouldOverrideUrlLoading like in following example:
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return false;
}
});
mWebView.loadUrl("https://drive.google.com/file/d/xx-xxxxxxxxxxxxxxx/view?usp=sharing");
Also you could get direct link to the file using sharable url you get above:
change this:
https://drive.google.com/file/d/xx-xxxxxxxxxxxxxxx/view?usp=sharing
to this:
https://drive.google.com/uc?export=download&id=xx-xxxxxxxxxxxxxxx
or to this:
https://docs.google.com/document/d/xx-xxxxxxxxxxxxxxx/export?format=pdf
I'm downloading a PDF from my server.
The server send me a HttpResponse with the InputStream of file's body.
I'm able to write it into a file but, when I try to read it with a PDF reader, it tells me that the file might be corrupted.
I've also noticed that the size of the PDF downloaded directly from web service is twice the size of the PDF downloaded via my application.
The code I use to download and write the PDF file is this:
String fileName = //FILENAME + ".pdf";
fileName = fileName.replaceAll("/", "_");
String extPath = Environment.getExternalStorageDirectory().toString();
String folderName = //FOLDERNAME;
try {
File folder = new File(extPath, folderName);
folder.mkdir();
File pdfFile = new File(folder, fileName);
pdfFile.createNewFile();
URL url = new URL(downloadURL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(pdfFile);
byte[] buffer = new byte[MEGABYTE];
int bufferLength;
while((bufferLength = inputStream.read(buffer))>0 ){
fileOutputStream.write(buffer, 0, bufferLength);
}
fileOutputStream.close();
Uri path = Uri.fromFile(pdfFile);
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(path, "application/pdf");
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(pdfIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(), "No Application available to view PDF", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
}
//otherStuff
Where I go wrong?
I've also noticed that inside the Headers of HttpResponse contains Content-type:text/html. It shoudld be something like text/pdf?
Your Downloading code seems correct. Based on that and on your comment:
I've also noticed that the size of the PDF downloaded directly from web service is twice the size of the PDF downloaded via my application."
I would suggest checking your URL. It appears that you might be downloading an html page instead of the pdf. To verify you are downloading correctly, change the download directory as follows:
//Default download directory
String extPath = Environment.DIRECTORY_DOWNLOADS;
And check the directory (via the file system, e.g. mount the phone to your computer or a file manager app) for the downloaded content to verify it is a pdf.
I'm newbie to Android, I'm trying to send some Images from Android to a RESTFul WCF.
By now I'm being able to select the Images from the Gallery and sending them to the Server.
the WCF is expecting the image as Stream
But I'm having problems with the Synced Images that get stored in the Tablet Like the Facebook or G+ photos. (I don't know if they are cached or something)
I'm using this function to get the path of the Image
public static String getRealPathFromURI(Context context, Uri contentUri) {
String path = null;
if (contentUri.getScheme().toString().compareTo("content")==0)
{
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
path = cursor.getString(column_index);
}
else
{
path = contentUri.getPath();
}
Log.i(TAG, path);
return path;
}
With that kind of images I get an internet path like:
https://fbcdn-sphotos-g-a.akamaihd.net/hphotos-ak-ash4/s2048x2048/432098_10151223392360790_398885469_n.jpg
Just for clarity and to remark. I get a "content" scheme.. so I get the path from the "if " something like:
content://com.sec.android.gallery3d.provider/picasa/item/5703464571893262194
To send it to the Server im using MultipartEntity, because I saw in others post here in SO to do so, like this:
((MultipartEntity) oInputEntity).addPart(
"fileContents",
new FileBody(new File(Utilities.getRealPathFromURI(context,
imageUri)),
"image/jpeg"));
With that kind of images I was getting a FileNotFoundEception I think it's because the image path is an Internet path, so the MultiPartEntity don't know how to retrieve it,
So I changed my method to download the image and now is working with this code
public static File getFileFromURI(Context context, Uri contentUri) {
String path = IntUtilities.getRealPathFromURI(context, contentUri);
Log.i(TAG, path);
final File file;
if (path.startsWith("http") || path.startsWith("/http") )
{
//if its an image form internet lets download it and save it in our directory and return that file
// Determine Uri of camera image to save.
final String fname = "BIR" + UUID.randomUUID() + ".jpg";
final File root = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "BIR");
root.mkdirs();
file = new File(root, fname);
try {
final URL url = new URL(path);
final HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(false);
urlConnection.connect();
final FileOutputStream fileOutput = new FileOutputStream(file);
final InputStream inputStream = urlConnection.getInputStream();
#SuppressWarnings("unused")
int downloadedSize = 0;
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
}
// close the output stream when done
fileOutput.close();
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
file = new File(path);
}
return file;
}
((MultipartEntity) oInputEntity).addPart(
"fileContents",
new FileBody(Utilities.getFileFromURI(context,
imageUri),
"image/jpeg"));
But I'm not comfortable with this solution, seems like double effort, I turned off my Wifi and 3g in the tablet, also turned off and on the tablet iself and I still see those images, so I'm guessing they got copied locally or cached on the tablet when they were synced for the first time. I looked for them when attached to my computer (in Windows Explorer) to see if they were there, but I dont see them, maybe I'm doing something wrong or dont know the storage folder.
The main reason that I dont like this solution is that if you don't have Internet on the moment, obviously the image will not be downloaded, and the app I'm making is supposed to work offline, and well.. the Image is there, there shouldn't be a request to internet to guess a local image.
Being said this, is there a way to find the real/physical path of this Photos that were synced, that have an http or https scheme to send this images using the MultiPartEntity?
Or another proper way to send this Images to the Server?
I really appreciate your help
from the chooser dialog , you can always get a bitmap
chooser-->$Result->getData() = imageUri
from the imageUri, get a Bitmap by running the following code:
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
Once you get the bitmap..,
you can put it to a fileSink
you can use a Hashmap to cache it in Memory
mBitMap = BitmapFactory.decodeStream(
mCR.openInputStream(imageUri), null, options);
OutputStream os = new FileOutputStream(f);
mBitMap.compress(Bitmap.CompressFormat.JPG, minVal, os);
mload.memoryCache.putbig(file.toURI().toURL().toString(), mBitMap);
and you can http POST the Bitmap directly by loading its ByteArray to the Entity...
case POST:
HttpPost httpPost = new HttpPost(url);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
float tmp = (float) 1024 * 1024 / bmp.getByteCount();
int minVal = (Math.round(tmp * 100) < 101) ? Math.round(tmp * 100): 100;
if (bmp.compress(Bitmap.CompressFormat.JPEG, minVal, stream)){
httpPost.setEntity(new ByteArrayEntity(stream.toByteArray()));
}else{ //TODO need to format actual message
handler.sendMessage(Message.obtain(handler,
HttpConnection.DID_ERROR, new Exception("ERR bitmap NG")));
}
background on the POST method is here
lazyloader project is a good template to use.
So why use mimeMultipartEntity with a file when you can operate directly on the bytes in the bitMap? As soon as you have a Uri, get a Bitmap and use the bitmap/ Uri pair for the basis of your interface to memCache, interface to HTTP POST, interface to fileSink used to retrieve local file when you have CacheMiss. This will help minimize doing everything on the basis of a file.
Think about using a Map [hashON(Uri.toString() :: bitMap] to store the images that you process locally. Then when you want to POST an image , you can just retrieve it from the map and POST its bytes directly in a "ByteArrayEntity".
I'm trying to share an image in an app I have made that downloads an Image and writes it to a file. But any time I try to share it, it says can't upload file or just does nothing. It's not coming up in the logcat so I'm kinda stuck for ideas on how to fix it.
The image that is downloaded is displayed in an image view like this
iView.setImageBitmap(im);
String path = ContentFromURL.Storage + "/temp.jpg";
File temp = new File(path);
uri = Uri.fromFile(temp);
iView.setImageURI(uri);
Asynch task to download file
HttpURLConnection connection;
try {
String url = params[0];
connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestProperty("Accept-Charset","UTF-8");
connection.connect();
InputStream input = connection.getInputStream();
image = BitmapFactory.decodeStream(input);
File temp = new File(Storage,"temp.jpg");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
FileOutputStream fo = new FileOutputStream(temp);
fo.write(bytes.toByteArray());
fo.close();
String path = temp.getAbsolutePath();
Log.d("Asynch", "image shuould exist");
SharePage.act.runOnUiThread(new Runnable()
{
public void run()
{
SharePage.setImage(image);
}
}
);
creating intent
twitterIntent = new Intent(Intent.ACTION_SEND);
twitterIntent.setClassName("com.twitter.android",packageName);
twitterIntent.setType("image/jpeg");
twitterIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(twitterIntent);
I know that I should use the built in android share thing but its not working either when I try to share the image
The problem was where I was trying to store the Image, I wanted to have it so that the user never saw the image and it was deleted when it wasn't needed anymore but the other apps didn't have access to the directory. So I have since moved it to the external storage directory.
I am right now working on an app which works as a book-stack,where user can read books of their choice,now what i am doing is,displaying the html pages that i've made,in a web-view in my application.
Now this application works only if the user has full time internet connection on his phone.
What exactly i want is when they first open the application,they would need internet connection and then the app should be able to download that page and store it in local database so the user can read it later on without having any internet connect.
So is there any possible way to download the html page and store it in local database so user can use the app even if he is not connected to internet?
I can post my code here if needed be.
Any smallest tip or help would be really great as i am stuck here since long now:(
EDIT 1:
So i successfully downloaded the HTLM page from the website,but now the problem that i am facing is,that i cannot see any of the images of the downloaded html. What can be a proper solution for this?
Here what's the mean of "Local Database"?
Preferred way is download your pages in either Internal Storage(/<data/data/<application_package_name>) (by default on non rooted device is private to your application) or on External Storage(public access). Then refer the pages from that storage area when user device has not a internet connection (offline mode).
Update: 1
To store those pages, you can use simple File read/write operation in Android.
For example:
String FILENAME = "hello_file";
String string = "hello world!";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
This example store file hello_file in your application's internal storage directory.
Update: 2 Download Web-Content
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet("http://www.xxxx.com");
HttpResponse response = httpClient.execute(httpGet, localContext);
String result = "";
BufferedReader reader = new BufferedReader(
new InputStreamReader(
response.getEntity().getContent()
)
);
String line = null;
while ((line = reader.readLine()) != null){
result += line + "\n";
}
// Now you have the whole HTML loaded on the result variable
So write result variable in File, using my update 1 code. Simple.. :-)
Don't forget to add these two permission in your android application's manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Code snippet for downloading web page. Check the comments in the code. Just provide the link ie www.mytestpage.com/story1.htm as downloadlink to the function
void Download(String downloadlink,int choice)
{
try {
String USERAGENT;
if(choice==0)
{
USERAGENT ="Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17";
}
else
{
USERAGENT ="Mozilla/5.0 (Linux; U; Android 2.1-update1; en-us; ADR6300 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17";
}
URL url = new URL(downloadlink);
//create the new connection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//set up some things on the connection
urlConnection.setRequestProperty("User-Agent", USERAGENT); //if you are not sure of user agent just set choice=0
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
//set the path where we want to save the file
File SDCardRoot = Environment.getExternalStorageDirectory();
File dir = new File (SDCardRoot.getAbsolutePath() + "/yourfolder");
if(!dir.exists())
{
dir.mkdirs();
}
File file = new File(dir, "filename"); //any name abc.html
//this will be used to write the downloaded data into the file we created
FileOutputStream fileOutput = new FileOutputStream(file);
//this will be used in reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
//this is the total size of the file
int totalSize = urlConnection.getContentLength();
//variable to store total downloaded bytes
int downloadedSize = 0;
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
//write the contents to the file
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
}
//close the output stream when done
fileOutput.close();
inputStream.close();
urlConnection.disconnect();
//catch some possible errors...
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}