Parse HTML with jsoup and string builder add white space in the final result.
First, it shows title and then strings from tag between the string title and tag p there is white space. thankyou
MainActivity
TextView tvidescription;
#Override
protected void onCreate ( Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
new Thread(new Runnable() {
#Override
public void run () {
final StringBuilder builder = new StringBuilder();
try {
Document doc = Jsoup.connect("https://jang.com.pk/news/497717").get();
Elements links = doc.select("p");
String title = doc.title();
builder.append(title);
for (Element link : links) {
builder.append("\n").append("\n").append(link.text());
}
} catch (IOException e) {
builder.append("Error : ").append(e.getMessage()).append("\n");
}
runOnUiThread(new Runnable() {
#Override
public void run () {
tvidescription.setText(builder);
}
});
}
}).start();
return null;
}
}
Try
doc.outputSettings().prettyPrint(false);
this will remove white spaces.
Related
I'm developing a simple Android application that has to scrape content of one website and then add this to the URL of another website that I have to scrape. The first scraping is okay, but the second gives me an error: "HTTP error fetching URL". The second URL is fine because when I give it to the first scraper everything is okay (but the URL is changing, so I cannot use it as a constraint). I think that I have to finish the thread of the first scraper somehow, but I don't know how.
My current code:
private void getBodyText() {
new Thread(new Runnable() {
#Override
public void run() {
final StringBuilder builder = new StringBuilder();
try {
String url="http://example.com";
Document doc = Jsoup.connect(url).get();
Element body = doc.body();
builder.append(body.text());
} catch (Exception e) {
builder.append("Error : ").append(e.getMessage()).append("\n");
}
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(builder.toString());
token1=builder.toString();
checkPairing();
}
});
}
}).start();
}
private void checkPairing() {
new Thread(new Runnable() {
#Override
public void run() {
final StringBuilder builder = new StringBuilder();
try {
String url="http:example.com/"+token1;
Document doc = Jsoup.connect(url).get();
Element body = doc.body();
builder.append(body.text());
} catch (Exception e) {
builder.append("Error : ").append(e.getMessage()).append("\n");
}
runOnUiThread(new Runnable() {
#Override
public void run() {
if (builder.toString()!="Not Found") {
tokenPar = builder.toString();
}
}
});
}
}).start();
}
I've also tried to execute the second function directly from onCreate() after the first scraper is executed but nothing changed.
I just want to read (-1) value which is the only value in website but I am not able to fetch this value Can any buddy guide me how to do that. I am getting the value of API url when I am pasting it in web browser and android is not fetching it. Link of API is given below.
Link OF API
Code I am trying is:
private void getWebsite() {
new Thread(new Runnable() {
#Override
public void run() {
final StringBuilder builder = new StringBuilder();
try {
Document doc = Jsoup.connect("https://api.thingspeak.com/channels/411172/feeds.json?results=1").get();
String title = doc.title();
Elements links = doc.select("[pre]");
builder.append(title).append("\n");
for (Element link : links) {
builder.append("\n").append("Link : ").append(link.attr("pre"))
.append("\n").append("Text : ").append(link.text());
}
} catch (IOException e) {
builder.append("Error : ").append(e.getMessage()).append("\n");
}
runOnUiThread(new Runnable() {
#Override
public void run() {
result.setText(builder.toString());
}
});
}
}).start();
}
Screen shot of web API call in browser
Error I am getting is Error: HTTP error fetching URL
As I see response from your API is JSON formatted you have to modify your code as follow
private void getWebsite() {
new Thread(new Runnable() {
#Override
public void run() {
final StringBuilder builder = new StringBuilder();
try {
Document doc = Jsoup.connect("https://api.thingspeak.com/channels/411172/feeds.json?results=1")
.ignoreContentType(true)
.get();
String json = doc.body().text();
builder.append(json);
} catch (IOException e) {
builder.append("Error : ").append(e.getMessage()).append("\n");
}
runOnUiThread(new Runnable() {
#Override
public void run() {
result.setText(builder.toString());
}
});
}
}).start();
}
Hello all i have a search activity into my app that works good if i try to search an item by tiping a text keyword but if i try to search an item that also contain a number app crash. For example if i try to search the text "home" search works good but if i search "home 3" app crash. The error is : exception-illegal-character-in-query-at-index I want that the search works good also by typing a text or a text + number exc..
Thank you
IMPORTANT :
the search activity call an encoded url, "ADSEARCH_URL"
public static final String ADSEARCH_URL="https://gjeme.com/apps/menjehere/index.php?action=searchAd&categoryId=%s&adcity=%s&q=%s";
This is the search activity :
public class SearchActivity extends AppCompatActivity {
Toolbar toolbar;
ListView lsv;
String categoryId,keyword,city;
ProgressDialog progressBar;
List<CatAdd> catAddList;
CateAdDisplayAdapter adapter;
Typeface typeface;
#SuppressLint("NewApi") #Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activty_search);
toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
toolbar.setTitle("Browse Ads");
setSupportActionBar(toolbar);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
getActionBarTextView();
typeface = Typeface.createFromAsset(getAssets(), "fonts/GandhiSerif- Bold.otf");
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
lsv = (ListView)findViewById(R.id.listView1);
catAddList = new ArrayList<CatAdd>();
categoryId = getIntent().getExtras().getString("categoryId", "0");
keyword = getIntent().getExtras().getString("keyword","keyword");
city = getIntent().getExtras().getString("city","city");
new SearchList().execute();
lsv.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Intent intent = new Intent(getApplicationContext(), BrowseAdsDetailActivity.class);
intent.putExtra("adId", String.valueOf(catAddList.get(arg2).getAddid()));
startActivity(intent);
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if(id==android.R.id.home)
{
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
}
private TextView getActionBarTextView() {
TextView titleTextView = null;
try {
Field f = toolbar.getClass().getDeclaredField("mTitleTextView");
f.setAccessible(true);
titleTextView = (TextView)f.get(toolbar);
titleTextView.setTypeface(typeface);
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {
}
return titleTextView;
}
class SearchList extends AsyncTask<Void, Void, Void>
{
String jsonStr = null;
CustomProgressDialog cd = new CustomProgressDialog();
#Override
protected void onPreExecute() {
super.onPreExecute();
cd.showdialog(SearchActivity.this, "Loading...");
}
#Override
protected Void doInBackground(Void... arg0) {
ServiceHandler sh = new ServiceHandler();
jsonStr = sh.makeServiceCall(String.format(Constants.ADSEARCH_URL,categoryId,city,keyword) , ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
JSONArray contacts = jsonObj.getJSONArray(Constants.TAG);
for (int i = contacts.length()-1; i > -1; i--) {
JSONObject c = contacts.getJSONObject(i);
String adId = c.getString(Constants.CAT_ADID);
String adTitle = c.getString(Constants.CAT_ADTITLE);
String adDes = c.getString(Constants.CAT_ADDES);
String adCreatedAt = c.getString("adCreatedAt");
String adcity= c.getString(Constants.CAT_CITY);
String adPrise= c.getString(Constants.CAT_PRICE);
JSONArray arrImages=c.getJSONArray("images");
ArrayList<String> imgArray=new ArrayList<String>();
for(int j=0;j<arrImages.length();j++)
{
JSONObject imgObj=arrImages.getJSONObject(j);
if(imgObj.has("imageName"))
{
imgArray.add(imgObj.getString("imageName"));
}
}
CatAdd v=new CatAdd();
v.setAddid(Integer.parseInt(adId));
v.setAdTitle(adTitle);
v.setAdDesc(adDes);
v.setAdCreatedAt(adCreatedAt);
v.setAdPrice(adPrise);
v.setImglist(imgArray);
v.setAdCity(adcity);
catAddList.add(v);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
cd.dismissdialog();
adapter = new CateAdDisplayAdapter(getApplicationContext(), catAddList);
lsv.setAdapter(adapter);
}
}
}
I think there isn't any problem with alpha-numeric characters here, but the SPACE is created one, while you are adding the text to URL.
Replace space(es) of searched keyword with %20 and hopefully you will find it fine.
I'm trying to send a variable string to Runnable, but find myself having to create two variables for this. One normal string content and one final string finalcontent that is assigned the content of the other string.
String content = "";
try {
content = response.body().string();
} catch (IOException e) {
// Handle exception
}
final String finalcontent = content;
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView text = (TextView)findViewById(R.id.textView);
text.setText(finalcontent);
}
});
Is this the normal way to do this or is there a better way to avoid creating two variables?
it's limitation of Java language design but you should be able to write
final String content;
try {
content = response.body().string();
} catch (IOException e) {
content = "";
// Handle exception
}
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView text = (TextView)findViewById(R.id.textView);
text.setText(content);
}
});
You may create a custom implementation of Runnable, here is an example
void foo(){
String content = "";
try {
content = response.body().string();
} catch (IOException e) {
// Handle exception
}
runOnUiThread(new MyCustomRunnable(content));
}
private class MyCustomRunnable implements Runnable {
private String content;
public MyCustomRunnable(String content) {
this.content = content;
}
#Override
public void run() {
TextView text = (TextView)findViewById(R.id.textView);
if (text != null) {
text.setText(content);
}
}
}
Why don't use RxJava?I think you just want to update UI after you get data from internet.
Observable observable = Observable.create(OnSubscribe()...)
.subscribeOn(Shceduler.io).observeOn(AndroidSchedulers.mainthread)
I want when server sends some response in form of WebView then immediately my activity gets refreshed and so WebView in form of banner ad.
I write code for display banner ad but ad is showing only when my activity recreated i.e. when I rotate my screen then banner is showing but when it is in same static mode then banner is not showing.
So, please let me know what I will do so that when server gave some response immediately it will be shown on my activity.
void startDemo() {
//Set Http Client Options
final OptimusHTTP client = new OptimusHTTP();
client.enableDebugging();
client.setMethod(OptimusHTTP.METHOD_POST);
client.setMode(OptimusHTTP.MODE_SEQ);
FreqDetector_Goertzel.getInstance().startRecording(new FreqDetector_Goertzel.RecordTaskListener() {
private String urlRedirect = "";
private String imgSmallBanner = "";
#Override
public void onSuccess(int val)
{
String pSet = pVal.getPatternSet(val, 5);
if (pSet != null) {
FreqDetector_Goertzel.getInstance().stopRecording();
EasyDeviceInfo deviceInfo = new EasyDeviceInfo(MainActivity.this);
final HashMap<String, String> device_params = new HashMap<>();
device_params.put("aid", deviceInfo.getAndroidID());
device_params.put("pattern", pSet);
if (isNetworkAvailable(MainActivity.this)) {
try {
client.makeRequest(MainActivity.this, new HttpReq(), Defaults.MATCHINGSERVER, device_params, new OptimusHTTP.ResponseListener() {
#Override
public void onSuccess(String s) {
try {
if (s != null && !s.contains("No Match Found"))
{
JSONObject jsonObject = null;
jsonObject = new JSONObject(s);
imgSmallBanner = Uri.decode(jsonObject.optString("smallImgUrl", "NA"));
urlRedirect = Uri.decode(jsonObject.optString("redirectUrl", "NA"));
loadAdvertisement(urlRedirect, imgSmallBanner);
} else {
//Did not match
startDemo();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(String s) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
} else {
//Internet not available. Do not do anything.
}
}
}
#Override
public void onFailure(String s) {
}
});
}
void loadAdvertisement(String clickUrl, String imgSmallName) {
String click_url;
String img_small_url;
stopDemo();
click_url = Uri.decode(Uri.encode(clickUrl));
img_small_url = imgSmallName;
StringBuilder htmlData2 = new StringBuilder();
htmlData2.append("<html><body style='margin:0;padding:0;background-color:black;'><a href='").append(click_url).append("' ><img src='").append(img_small_url).append("' height=50 style='margin:0 auto;display:block;' /></a></body></html>");
webView_img_small.loadDataWithBaseURL("file:///android_asset/", htmlData2.toString(), "text/html", "utf-8", null);
webView_img_small.setVisibility(View.VISIBLE);
/* What I will do here so when server sends response it will immediately being refreshed and shown on activity without recreating it.*/ }
here you can find some response: http://developer.android.com/guide/topics/ui/how-android-draws.html
for me a call to invalidate() only refresh the view and a call to requestLayout() refresh the view and compute the size of the view in the screen.
You can try to use Activity.recreate(). This method will destroy your current Activity and create a new Activity same way when you rotate device.
Hope this helps.