I am having an android application requirement where i need to open saved web pages, how to do the same?? FIrst of all, how can we save a webpage with its dependancies on android and later open it in your applications? Any inputs will be of great help!
First of all, let's save the webarchive from webview
private void initUI{
webView = (WebView) findViewById(R.id.webView);
AndroidWebClient client = new AndroidWebClient();
webView.setWebViewClient(client);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
}
private class AndroidWebClient extends WebViewClient {
#Override
public void onPageStarted(WebView view, String url,
android.graphics.Bitmap favicon) {
}
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.saveWebArchive(Environment.getExternalStorageDirectory()
+ File.separator +"myArchive"+".mht");
// our webarchive wull be available now at the above provided location with name "myArchive"+".mht"
}
public void onLoadResource(WebView view, String url) {
}
}
The way to save the webarchive is same in all APIs but to load it, varies
for API less than Kitkat
private void loadArchive(){
String rawData = null;
try {
rawData = getStringFromFile(Environment.getExternalStorageDirectory()
+ File.separator+"myArchive"+".mht");
} catch (Exception e) {
e.printStackTrace();
}
webView.loadDataWithBaseURL(null, rawData, "application/x-webarchive-xml", "UTF-8", null);
}
public String getStringFromFile (String filePath) throws Exception {
File fl = new File(filePath);
FileInputStream fin = new FileInputStream(fl);
String ret = convertStreamToString(fin);
//Make sure you close all streams.
fin.close();
return ret;
}
public String convertStreamToString(InputStream is) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
reader.close();
return sb.toString();
}
for Kitkat and above
private void loadArchive(){
webView.loadUrl("file:///"+Environment.getExternalStorageDirectory()
+ File.separator+"myArchive"+".mht");
}
This is how I would implement that:
Save original web page into a file
Parse saved file and get all image URLs. Save images into the same directory.
Convert URL of the images(bind all links to a local copies)
Here is simple code which demonstrate this idea:
String download(String url) throws Exception {
String filename = "local.html";
save(url, filename);
List<String> imageLinks = getImageURLs(filename);
for (String imageLink : imageLinks) {
String imageFileName = getImageName(imageLink);
save(imageLink, imageFileName);
}
convertImageURLs(filename);
return filename;
}
void save(String url, String saveTo) throws Exception {
HttpURLConnection conn = (HttpURLConnection) (new URL(url)).openConnection();
conn.connect();
InputStream is = conn.getInputStream();
save(is, saveTo);
}
void save(InputStream is, String saveTo) {
// save actual content
}
List<String> getImageURLs(String localHtmlFile) {
// parse localHtmlFile and get all URLs for the images
return Collections.EMPTY_LIST;
}
String getImageName(String imageLink) {
// get image name, from url
return null;
}
void convertImageURLs(String localHtmlFile) {
// convert all URLs of the images, something like:
// <img src="original_url"> -> <img src="local_url">
}
Related
I would like to select a pdf file from file manager in android and convert it to text so text to speech can read it. I'm following this documentation from android developer site; however, this example is for opening a text file. I'm using PdfReader class/ library in order to open the file and convert to text. but I don't know how to integrate that with Uri.
Here's the code I need to convert from pdf to text using PdfReader
PdfReader pdfReader = new PdfReader(file.getPath());
stringParser = PdfTextExtractor.getTextFromPage(pdfReader, 1).trim();
pdfReader.close();
I'm calling file manager using intent so the user can select a pdf file
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("*/*");
startActivityForResult(intent, READ_REQUEST_CODE);
}
});
then I'm getting uri and opening file
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
if(resultData != null) {
Uri uri = resultData.getData();
Toast.makeText(MainActivity.this, filePath , Toast.LENGTH_LONG).show();
readPdfFile(uri);
}
}
}
private String readTextFromUri(Uri uri) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
try (InputStream inputStream =
getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(
new InputStreamReader(Objects.requireNonNull(inputStream)))) {
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
}
return stringBuilder.toString();
}
public class SyncPdfTextExtractor {
// TODO: When you have your own Premium account credentials, put them down here:
private static final String CLIENT_ID = "FREE_TRIAL_ACCOUNT";
private static final String CLIENT_SECRET = "PUBLIC_SECRET";
private static final String ENDPOINT = "https://api.whatsmate.net/v1/pdf/extract?url=";
/**
* Entry Point
*/
public static void main(String[] args) throws Exception {
// TODO: Specify the URL of your small PDF document (less than 1MB and 10 pages)
// To extract text from bigger PDf document, you need to use the async method.
String url = "https://www.harvesthousepublishers.com/data/files/excerpts/9780736948487_exc.pdf";
SyncPdfTextExtractor.extractText(url);
}
/**
* Extracts the text from an online PDF document.
*/
public static void extractText(String pdfUrl) throws Exception {
URL url = new URL(ENDPOINT + pdfUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
conn.setRequestProperty("X-WM-CLIENT-ID", CLIENT_ID);
conn.setRequestProperty("X-WM-CLIENT-SECRET", CLIENT_SECRET);
int statusCode = conn.getResponseCode();
System.out.println("Status Code: " + statusCode);
InputStream is = null;
if (statusCode == 200) {
is = conn.getInputStream();
System.out.println("PDF text is shown below");
System.out.println("=======================");
} else {
is = conn.getErrorStream();
System.err.println("Something is wrong:");
}
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
}
}
------------------------------------
Copying above code follow below Steps-
Specify the URL of your online PDF document on line 20.
Replace the Client ID and Secret on lines 10 and 11 if you have your own credentials.
use this
Gradle :-
implementation 'com.itextpdf:itextg:5.5.10'
try {
String parsedText="";
PdfReader reader = new PdfReader(yourPdfPath);
int n = reader.getNumberOfPages();
for (int i = 0; i <n ; i++) {
parsedText = parsedText+PdfTextExtractor.getTextFromPage(reader, i+1).trim()+"\n"; //Extracting the content from the different pages
}
System.out.println(parsedText);
reader.close();
} catch (Exception e) {
System.out.println(e);
}
I have the following assynctask implemented. Its usage is pretty simple, and so works as intended so far. get a url, post to it, get its contents, write them to a file. the hard part begins now
QUESTION:
I require reusage of this piece of code multiple times for multiple different files. How can i pass the file as a variable on assynctask call alongside the url?
//class to call a url and save it to a local file
private class url_to_file extends AsyncTask<String, Integer, String> {
protected String[] doInBackground(String... input) {
//function to call url and postback contents
return callpost(input[0]);
}
protected void onProgressUpdate(Integer... progress) {
//Yet to code
}
protected void onPostExecute(String result) {
//function to write content to text file
writeStringAsFile( result, "file.xml" ,getApplicationContext());
}
}
EDIT:
Purelly as reference, the function i use to read, write from file and call url
//saves a txt (etc, xml as well) file to directory,replacing previous. if directory is left empty, save to assets
public static void writeStringAsFile(final String fileContents, String fileName ,Context context) {
try {
FileWriter out = new FileWriter(new File(context.getFilesDir(), fileName));
out.write(fileContents);
out.close();
} catch (IOException e) {
}
}
//read file, returns its contents
public static String readFileAsString(String fileName,Context context) {
StringBuilder stringBuilder = new StringBuilder();
String line;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(new File(context.getFilesDir(), fileName)));
while ((line = in.readLine()) != null) stringBuilder.append(line);
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
return stringBuilder.toString();
}
//calls a page. Returns its contents
public String callpost (String... strings)
{
StringBuilder content = new StringBuilder();
try
{
// create a url object
URL url = new URL(strings[0]);
// create a urlconnection object
URLConnection urlConnection = url.openConnection();
// wrap the urlconnection in a bufferedreader
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line;
// read from the urlconnection via the bufferedreader
while ((line = bufferedReader.readLine()) != null)
{
content.append(line + "\n");
}
bufferedReader.close();
}
catch(Exception e)
{
e.printStackTrace();
}
return content.toString();
}
EDIT:
Removed second question as it had nothing to do with the rest and would just confuse people to see the thread
Kudos #FirstOne for his help up at comments
this made it for me
//class to call a url and save it to a local file
private class url_to_file extends AsyncTask<String, Integer, String> {
protected String file;
public void setFile(String input)
{
file=input;
}
protected String[] doInBackground(String... input) {
//function to call url and postback contents
return callpost(input[0]);
}
protected void onProgressUpdate(Integer... progress) {
//Yet to code
}
protected void onPostExecute(String result) {
//function to write content to text file
writeStringAsFile( result, file ,getApplicationContext());
}
}
I want to download images and cache them base64 encoded in database, when i'm online. When my app is offline, i would replace all image tags by the appropriate strings. But if i show them, there are always question mark icons, which e.g. are shown, when an image is not found. (There's no error or warning in LogCat). How could I show the image?
I created a short example app:
#Override
protected void onCreate(Bundle savedInstanceState)
{
activity = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webview);
webView.setWebViewClient(new MyWebViewClient());
webView.setWebChromeClient(new MyWebChromeClient());
webView.setHttpAuthUsernamePassword(host, "", user, password);
new Image().execute("");
}
public String getUrlContent(String urlstring) throws IOException
{
URL url = new URL(urlstring);
URLConnection connection = url.openConnection();
Authenticator.setDefault(new Authenticator()
{
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user, password .toCharArray());
}
});
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod("GET");
httpConnection.connect();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK)
{
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(httpConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String inputLine;
while ((inputLine = bufferedReader.readLine()) != null)
stringBuilder.append(inputLine + "\n");
return stringBuilder.toString();
}
return null;
}
private class Image extends AsyncTask<String, Void, Boolean>
{
private String img;
#Override
protected Boolean doInBackground(String... string)
{
try
{
img = new String(Base64.encodeToString(getUrlContent(url).getBytes(),
Base64.DEFAULT));
} catch (IOException e)
{
e.printStackTrace();
}
return true;
}
#Override
protected void onPostExecute(Boolean doInBackground)
{
String html = "<html><img src=\"data:image/jpeg;base64," + img + "\" /></html>";
webView.loadDataWithBaseURL("http://example.com/my.jpg", html, "text/html", null, url);
webView.loadData(html, "text/html", "UTF-8");
}
}
private class MyWebViewClient extends WebViewClient
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
return true;
}
#Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl)
{
Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_LONG)
.show();
}
#Override
public void onReceivedHttpAuthRequest(WebView view,
HttpAuthHandler handler, String host, String realm)
{
handler.proceed(user, password);
}
}
private class MyWebChromeClient extends WebChromeClient
{
#Override
public void onProgressChanged(WebView view, int progress)
{
// Activities and WebViews measure progress with different scales.
// The progress meter will automatically disappear when we reach
// 100%
activity.setProgress(progress * 1000);
}
#Override
public void onReachedMaxAppCacheSize(long spaceNeeded,
long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
{
quotaUpdater.updateQuota(spaceNeeded * 2);
}
}
The Method to download is incorrect for images (I think you have explicitly read bytes, not Strings for images).
Here's the correct download code:
public String getUrlContent(String urlstring) throws IOException
{
byte[] imageRaw = null;
URL url = new URL(urlstring);
Authenticator.setDefault(new Authenticator(){
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password.toCharArray());
}});
HttpURLConnection urlConnection = (HttpURLConnection) url
.openConnection();
urlConnection.setUseCaches(false);
urlConnection.connect();
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK)
{
try
{
InputStream in = new BufferedInputStream(
urlConnection.getInputStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
int c;
while ((c = in.read()) != -1)
{
out.write(c);
}
out.flush();
imageRaw = out.toByteArray();
urlConnection.disconnect();
in.close();
out.close();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return Base64.encodeToString(imageRaw, Base64.DEFAULT);
}
return null;
}
Thanks to this two posts: How to display image with WebView loaddata? and How to do HTTP authentication in android?
I have an ".HTML" file which is stored in the "res\raw" folder.
I used the following code to display the contents of my file:
static String TAG="WebPageShowActivity";
WebView mWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webpagedisplay);
String summary = readRawTextFile(this,R.raw.spotlighterhelp);
//getResources().openRawResource(R.raw.spotlighterhelp).toString();
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadDataWithBaseURL (null,summary, "text/html","ASCII" ,null);
}
public static String readRawTextFile(Context ctx, int resId)
{
InputStream inputStream = ctx.getResources().openRawResource(resId);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
StringBuilder text = new StringBuilder();
try {
while (( line = buffreader.readLine()) != null) {
text.append(line);
}
} catch (IOException e) {
return null;
}
Log.e(TAG, "file content: "+text.toString());
return text.toString();
}
now, my problem is: Whatever be the type of encoding, it is not displaying special characters like " or ' What do I do so that these characters are shown too?
Following is the output I am getting
I think it may works, Try to use UTF-8 instead of ASCII for your webView.
mWebView.loadDataWithBaseURL (null,summary, "text/html","UTF-8" ,null);
I have the HTML files in assets named n0.html, n1.html, etc. I want to create a listview with links to these files, but I don't know how to do it.
I have such a decision with a raw folder. How should I change it to assets files?
public class ViewActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view);
Bundle bundle = getIntent().getExtras();
String itemname = "n" + bundle.getString("defStrID"); //getting string and forming resource name
Context context = getBaseContext(); //getting context
// Reading text file from resources by name
String text = readRawTextFile(context, getResources().getIdentifier(itemname, "raw", "ru.falcon5f.carguide;"));
WebView wWebView = (WebView) findViewById(R.id.webView);
String summary = "<!Doctype html><html><head><meta charset=utf-8></head><body>" + text + "</body></html>";
wWebView.loadData(summary, "text/html", "utf-8"); //uploading text to webview
}
public static String readRawTextFile(Context ctx, int resId) // Reading text raw txt file
{
InputStream inputStream = ctx.getResources().openRawResource(resId);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
StringBuilder text = new StringBuilder();
try {
while (( line = buffreader.readLine()) != null) {
text.append(line);
text.append('\n');
}
}
catch (IOException e) {
return null;
}
return text.toString();
}
}
Added
I'm sorry if I ask too stupid questions and I ask too much, but I want to work my first application. This is very important for me. So it consists of two activities:
ViewActivity which I've changed according to your advices
public class ViewActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view);
Bundle bundle = getIntent().getExtras();
String htmlFileName = "n" + bundle.getString("defStrID"); // Getting file name
Context context = getBaseContext(); // Getting context. You still need that
// Reading text file from resources by name
try {
String text = readAssetTextFile(context, htmlFileName);
WebView wWebView = (WebView) findViewById(R.id.webView);
String summary = "<!Doctype html><html><head><meta charset=utf-8></head><body>" + text + "</body></html>";
wWebView.loadData(summary, "text/html", "utf-8"); // Uploading text to webview
}
catch (IOException e) {
Log.e("TAG", e); // Note that you will need to import android.util.Log
}
}
public static String readAssetTextFile(Context ctx, String fileName) throws IOException // Reading the HTML file from assets
{
InputStream inputStream = ctx.getAssets().open(fileName);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line;
StringBuilder text = new StringBuilder();
try {
while (( line = buffreader.readLine()) != null) {
text.append(line);
text.append('\n');
}
}
catch (IOException e) {
return null;
}
return text.toString();
}
}
In Log.e("TAG", e);, Eclipse wants to change type of "e" to "String".
How can I fix this?
It will not be that much different. You know that you can access a file in the assets like this:
InputStream inputStream = ctx.getAssets().open(fileName);
You can place this instead of your line InputStream inputStream = ctx.getResources().openRawResource(resId);. Then you need to pass in the correct file name. When working with assets you need not use IDs.
Editing your snippet:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view);
Bundle bundle = getIntent().getExtras();
String htmlFileName = "n" + bundle.getString("defStrID") + ".html"; // Getting file name
Context context = getBaseContext(); // Getting context. You still need that
// Reading text file from resources by name
try {
String text = readAssetTextFile(context, htmlFileName);
WebView wWebView = (WebView) findViewById(R.id.webView);
String summary = "<!Doctype html><html><head><meta charset=utf-8></head><body>" + text + "</body></html>";
wWebView.loadData(summary, "text/html", "utf-8"); // Uploading text to webview
} catch (IOException e) {
Log.e("TAG", "Exception thrown", e); // Note that you will need to import android.util.Log
}
}
public static String readAssetTextFile(Context ctx, String fileName) // Reading HTML file from assets
{
InputStream inputStream = ctx.getAssets().open(fileName);
.....