I want to get an HTML from a web page, remove some tags from the code and display it using a TextView... But those HTMLs are too big to be temporaly stored into a String...
When I try this way:
String html = "myBigHTML";
myTextView.setText(fromHtml(html));
compiler says error: constant string too long
If I put the html into a .txt and try this way:
InputStream is = getAssets().open("html.txt");
tvTeste.setText(fromHtml(convertStreamToString(is)));
public static 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();
}
It works but the app gets soooo slow, almost freezes... And also, if I store it in a .txt I couldn't work with the tags...
.:: EDIT ::.
My onCreate() method as asked...
private TextView tvTeste;
private InputStream is;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_frequencia);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
tvTeste = (TextView)findViewById(R.id.tvTeste);
try {
is = getAssets().open("html.txt");
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String strLine;
List<String> stringList = new ArrayList<>();
try {
while ((strLine = br.readLine()) != null) {
stringList.add(strLine);
}
} catch (Exception e) {
e.printStackTrace();
}
tvTeste.setText(fromHtml(TextUtils.join("",stringList)));
}
Let's try this: each line of HTML text is a String. Each String is inside a List of String.
So, some pseudocode:
List<String> stringList = new ArrayList<>();
while (htmlHandler.next()) {
stringList.add(fromHtml(htmlHandler.readLine()));
}
myTextView.setText(joinStringArray(stringList));
Where joinStringArray uses a StringBuilder to produce a single big String object.
Basically you shouldn't read the entire web page, but you should read it sequentially.
Another point to mark. You should avoid any time consuming process that blocks the activity. try the same using, for example an AsyncTask.
Please check https://developer.android.com/reference/android/os/AsyncTask.html
Related
i want parse a String into a Class Instance.
My Data come from a .csv.
Code:
#Override
public List<Strasse> getByStadtId(Stadt stadtId){
return repo.findByStadtId(stadtId);
}
#Override
public void saveStrassenData() {
StringBuilder builder = new StringBuilder();
try {
BufferedReader bufferReader = new BufferedReader(new FileReader("src/main/resources/csv/strassen.csv"));
while((line = bufferReader.readLine()) != null) {
String [] data=line.split(",");
Strasse strasse = new Strasse();
Stadt stadt = new Stadt();
strasse.setId(Long.parseLong(data[0]));
strasse.setName(data[1]);
strasse.setVerwaltungsKuerzel(data[2]);
strasse.setStadt(data[3]);
repo.save(strasse);
}
}
catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
In Picture 1 you can see my error.
Picture of the Code
My Class is in the pictures:
The .csv
setStadt doesn't take a String. You need to create an instance of Stadt and then you could set it's id.
Something like that:
Stadt stadt = new Stadt();
stadt.setId(data[3]);
strasse.setStadt(stadt);
The handling of Stadt and validation of Strasse is missing.
#Override
public void saveStrassenData() {
Charset charset = StandardCharsets.ISO_8859_1; // Or UTF_8.
try (InputStream in = getClass().getResourceAsStream("/csv/strassen.csv");
BufferedReader bufferReader = new BufferedReader(
new InputStreamReader(in, charset))) {
while((line = bufferReader.readLine()) != null) {
String[] data=line.split(",\\s*");
Strasse straße = new Strasse();
long stadtId = Long.parseLong(data[3]);
Stadt stadt = new Stadt(); // repo.getStadtById(stadtId);
stadt.setId(stadtId); //
straße.setId(Long.parseLong(data[0]));
straße.setName(data[1]);
straße.setVerwaltungsKuerzel(data[2]);
straße.setStadt(stadt; // <--
repo.save(straße);
}
}
catch (IOException e) { // Better method with throws IOException.
e.printStackTrace(); // Log.
}
}
Also the old utility class FileReader uses the default charset, for a German Windows Cp-1252, a superset of ISO-8859-1. For a server likely UTF-8. Better state the charset explicitly, especially when you provide it yourself as read-only resource.
I was being a bit naive, thinking I can read webpages the same way as you do in Java, but apparently you need to use threads or AsyncTask. Which I have no prior experience in and are proving to be hassle.
I've read http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html (3. point) which I semi understand but when I try to implement into my problem it all falls apart.
Here's my problem:
I need to read from an URL, it's a RSS feed.
Parse it all together
Insert it into ListView (arrayadapter)
This is my AsyncTask class, that I tried to recreate. I just want it to return a buffered reader, or the whole page but it's always null.
private class DownloadWebPageTask extends AsyncTask<String, Void, BufferedReader> {
#Override
protected BufferedReader doInBackground(String... urls) {
BufferedReader bs;
URL url = null;
try {
url = new URL(urls[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
bs = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
return bs;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(BufferedReader result) {
br = result;
}
}
public RSS() throws IOException, ExecutionException, InterruptedException {
DownloadWebPageTask dl = new DownloadWebPageTask();
dl.execute(new String[] {"http://www.promet.si/dc/PROMET.ROADEVENTS.PP.RSS.SL"});
}
I'm sorry if this is a stupid question, but I don't fully understand posts explaining this and I have to solve this problem. I just need the page's content in any way shape or form. (Can be a String, BufferedReader)
#Override
protected String doInBackground(String... urls) throws IOException {
URLConnection connection = new URL(urls[0]).openConnection();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()),"UTF-8");
StringBuilder stringBuilder = new StringBuilder();
String buffer;
while ((buffer = bufferedReader.readLine()) != null) {
stringBuilder.append(buffer);
}
return stringBuilder.toString();
}
Use the buffered reader to read line by line in the background thread, and make it return string.
I am trying to get the text from a file and apply it to a textView. However, I am being returned with the file path as shown below.
#Override
public void onViewCreated(View view, Bundle savedInstanceState){
tv = (TextView) getActivity().findViewById(R.id.clockText);
// Displaying the user details on the screen
try {
getFileText();
} catch (IOException e) {
e.printStackTrace();
}
}
public void getFileText() throws IOException {
File path = getActivity().getExternalFilesDir(null); //sd card
File file = new File(path, "alarmString.txt"); //saves in Android/
FileInputStream stream = new FileInputStream(file);
try{
stream.read();
tv.setText(file.toString());
} finally {
stream.close();
}
}
The result is being "Android/data/foldername/example/files/alarmString.txt" instead of the time declared by the user in a different activity for example: 18:05
public String getFileContent(File file) throws IOException {
String str = "";
BufferedReader bf = null;
try {
bf = new BufferedReader(new FileReader(file));
while(bf.ready())
str += bf.readLine();
} catch (FileNotFoundException e){
Log.d("FileNotFound", "Couldn't find the File");
} finally {
bf.close();
}
return str;
}
Use a BufferedReader and FileReader instead of reading the bytes. You used
stream.read();
what gives you one byte of your file.
tv.setText(file.toString());
will set your TextView to the output of the file.toString() methods output and not to the files content.
do it as follow
#Override
public void onViewCreated(View view, Bundle savedInstanceState){
tv = (TextView) getActivity().findViewById(R.id.clockText);
// Displaying the user details on the screen
try {
tv.setText(getFileText());
} catch (IOException e) {
e.printStackTrace();
}
}
public String getFileText() throws IOException {
File path = getActivity().getExternalFilesDir(null); //sd card
File file = new File(path, "alarmString.txt"); //saves in Android/
BufferedReader br = new BufferedReader(new FileReader(file));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
} finally {
br.close();
}
return sb.toString()
}
you have to return a string from getFileText function and then set that string to the text view.
You are setting file.toString which returns file path. If you want to set the data which is present in the file you need to read stream and append to stringbuffer in while loop until text gets over in file and finally set stringbuffer.toString to textview.
I'm creating an app where I need a function to get plain text from a website. I am able to get the text and print it out on my PC just fine, but when I try running it on an Android device, the app won't start.
I believe it has something to do with throwing an IOException. I've been reading that I am not supposed to do that because I don't define the interface. Is there a way to get around this? Android Studio won't compile my code if I don't throw the exception.
The function:
public String getText(String site) throws IOException {
// Make a URL to the web page
URL url = new URL(site);
// Get the input stream through URL Connection
URLConnection con = url.openConnection();
InputStream is =con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// read each line and return the final text
String res = "";
String line = null;
while ((line = br.readLine()) != null) {
//System.out.println(line);
res += line;
}
return res;
}
And this is how Android Studio makes me run it in the onCreate method:
String text = null;
try {
text = getText("http://myWebsite.com");
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
First, read your logcat - you should see your exception there with full stacktrace. Second, there is nothing wrong with catching IOException, but you must do something with it once cached - like inform user of problem in functionality - like no more space, etc.
And this is how Android Studio makes me run it in the onCreate method:
this is a problem, because your are getting data from your site on UI thread, you must do it from worker thread, ie. AsyncTask.
You can not do it in the main thread
try this
class MyTask extends AsyncTask<Void, Void, String>{
private String site;
MyTask(String site) {
this.site = site;
}
#Override
protected String doInBackground(Void... params) {
try {
URL url = new URL(site);
URLConnection con = url.openConnection();
InputStream is =con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// read each line and return the final text
String res = "";
String line = null;
while ((line = br.readLine()) != null) {
//System.out.println(line);
res += line;
}
return res;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(s != null){
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
}
}
}
where to get a string is used as
new MyTask("http://myWebsite.com").execute()
I had a method like this in an Android app reading a raw file:
public String inputStreamToString(InputStream isTwo) throws IOException {
StringBuffer sBuffer = new StringBuffer();
DataInputStream dataIO = new DataInputStream(isTwo);
String strLineTwo = null;
while ((strLineTwo = dataIO.readLine()) != null) {
sBuffer.append(strLineTwo + "\n");
}
dataIO.close();
isTwo.close();
return sBuffer.toString();
}
However, the DataInputStream object appears to be deprecated now. I researched it and heard it is better to wrap the readline() with a BufferedInputStream. Can someone help me finish his (fill in the missing line)? I am not sure how to declare the br var. This is what I have so far:
public String inputStreamToString(InputStream isTwo) throws IOException {
String strLineTwo = null;
BufferedReader br = null;
StringBuffer sBuffer = new StringBuffer();
InputStreamReader dataIO = new InputStreamReader(isTwo);
while ((strLineTwo = br.readLine()) != null) {
sBuffer.append(strLineTwo + "\n");
}
dataIO.close();
isTwo.close();
return sBuffer.toString();
Here is the preceding code I have not touched yet that calls this method:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tech);
InputStream iFileTwo = getResources().openRawResource(R.raw.testing);
try {
TextView helpText = (TextView) findViewById(R.id.tvStream);
String strFileTwo = inputStreamToString(iFileTwo);
helpText.setText(strFileTwo);
} catch (Exception e) {
Log.e(DEBUG_TAG_THREE, "InputStreamToString failure", e);
}
}
Also, I want to make sure it works from Android 2.3 to 4.2 (current). Thanks for any help.
This is how I would write it. This has much less overhead and preserves the newlines as they were originally.
public String inputStreamToString(InputStream in) throws IOException {
StringBuilder out = new StringBuilder();
char[] chars = new char[1024];
Reader reader = new InputStreamReader(in /*, CHARSET_TO_USE */);
try {
for (int len; (len = reader.read(chars)) > 0; )
out.append(chars, 0, len);
} finally {
try {
in.close();
} catch (IOException ignored) {
}
}
return out.toString();
}
Just a suggestion, if you are migrating, then why not use the IOUtils from libraries like apache commons etc which actually take care of managing your streams and also save you with lot of errorneous conditions