Android : How to set image with url by a subroutine - android

I'm creating a subroutine to get an image using a url. Here is a similar subroutine that I used to parse text from an XML into my UI:
public void loading(int index) {
final Handler handler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
try {
arrayList = XMLPullParser.parse("http://localhost/news.xml", "news", 1, 2, 3);
//URL url = new URL("http://localhost/"+arrayList2.get(1).toString());
//final Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
handler.post(new Runnable() {
public void run() {
chk1.setText(arrayList.get(0).toString());
chk2.setText(arrayList.get(1).toString());
chk3.setText(arrayList.get(2).toString());
try {
img1.setImageBitmap(bitmap("http://localhost/1.jpg"));
img2.setImageBitmap(bitmap("http://localhost/2.jpg"));
img3.setImageBitmap(bitmap("http://localhost/3.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
});
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}).start();
}
Here is the change I made to load the images:
static Bitmap bmp;
public Bitmap bitmap(String url_input) throws IOException {
final String get_url = url_input;
new Thread(new Runnable() {
#Override
public void run() {
try {
final URL url = new URL(get_url);
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
return bmp;
}
The subroutine works when parsing text but doesn't work properly when loading the bitmaps. I need to set images to 3 image buttons and want to use a subroutine to do it.
I know it should not use static for my bmp variable, it's just a test to let me know if it works.

Your bitmaps are not displayed because your threading setup is incorrect. Your bitmap method returns before thread it started has finished. Also you are using static variable used by all threads.
I recommend to use AsyncTask and do all your background work there - there is no need to spawn separate threads for every image. Also pay attention to assign values to your checkboxes and images in onPostExecute method because these can be assigned only in main (gui) thread.

You could do it something like this. This asserts that you have the code in an activity. But the thread handling should probably be changes to use an AsyncTask instead.
bitmap(img1, "http://localhost/1.jpg");
.
.
.
public void bitmap(final ImageView imageView, String url_input) throws IOException {
final String get_url = url_input;
new Thread(new Runnable() {
#Override
public void run() {
try {
final URL url = new URL(get_url);
final Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
if (bmp != null) {
runOnUiThread(new Runnable() {
#Override
public void run() {
imageView.setImageBitmap(bmp);
}
});
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}

Related

Two jsoup scrapers in one Android app doesn't work

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.

Avoid using two variables to send variable information to Runnable

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)

How to edit views when waiting for a thread?

I load my articles from my wordpress webpage. And want to display them in my app.
In order to be allowed to wait for a internet response I had to create a Thread.
Using this method:
private void loadArticles(final String url) {
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
//Get my data and run createArticles();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
Then in the createArticles function I try to use my function addViewToParent(...) and I get an error that says:
Only the original thread that created a view hierarchy can touch its
views.
How can i work around this problem?
EDIT: I use these networking functions if it matters...
//Connect to the url
URL pageURL = new URL(url);
HttpURLConnection connection = (HttpURLConnection) pageURL.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream())
);
If you want to modify your Views, e.g. show your article, you have to run the code on the UI/main thread. To achieve this, you could call run runOnUiThread() in your Activity:
private void loadArticles(final String url) {
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
//Get my data ...
runOnUiThread(new Runnable() {
public void run() {
// modify Views here
createArticles();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
You need to use function runOnUiThread. This is function for user interface thread.
private void loadArticles(final String url) {
//Get my data ...
runOnUiThread(new Runnable() {
public void run() {
// modify Views here
createArticles();
}
});
});
Just use a Handler instead, so you'll have access to the UI Thread:
new Handler().post(new Runnable(){
#Override
public void run() {
try {
//Get my data and run createArticles();
} catch (Exception e) {
e.printStackTrace();
}
}
});

Only the original thread that created a view hierarchy can touch its views in android [duplicate]

This question already has answers here:
Android "Only the original thread that created a view hierarchy can touch its views."
(33 answers)
Closed 6 years ago.
I want my page to show an image, but when I run it, get the error: "Only the original thread that created a view hierarchy can touch its views" , could anyone tell me how to fix it?here is my code:
show.java:
public class Show extends Base{
String nameValue, style_of_cookingValue, ingredientValue, stepValue, imageValue, costValue;
TextView name, style_of_cooking, ingredient, step, cost;
ImageView image;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recipe);
nameValue = getIntent().getStringExtra("name");
style_of_cookingValue = getIntent().getStringExtra("style_of_cooking");
ingredientValue = getIntent().getStringExtra("ingredient");
stepValue = getIntent().getStringExtra("step");
costValue = getIntent().getStringExtra("cost");
imageValue = getIntent().getStringExtra("image");
name = (TextView) findViewById(R.id.nameContent);
style_of_cooking = (TextView) findViewById(R.id.typeContent);
ingredient = (TextView) findViewById(R.id.ingredientContent);
step = (TextView) findViewById(R.id.stepContent);
cost = (TextView) findViewById(R.id.costContent);
image = (ImageView) findViewById(R.id.image);
name.setText(nameValue);
style_of_cooking.setText(style_of_cookingValue);
ingredient.setText(ingredientValue);
step.setText(stepValue);
cost.setText(costValue);
new Thread(new Runnable(){
public void run() {
try {
Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageValue).getContent());
image.setImageBitmap(bitmap);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
#Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()) {
case android.R.id.home:
finish();
break;
}
return true;
}
}
You cannot call image.setImageBitmap(bitmap); inside a Thread other than the main thread.
Ideally you should use an AsyncTask or some sort of mechanism where you can pass a callback interface to the main thread and set the bitmap. But for a quick and dirty solution try this:
new Thread(new Runnable(){
public void run() {
try {
Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageValue).getContent());
Show.this.runOnUiThread(new Runnable() {
#Override
public void run() {
image.setImageBitmap(bitmap);
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();

Download image from a url and show in a listview

I am fetching title, date and image from an online xml file and storing it in a arraylist. I have taken 3 different arraylists for storing title , date and image.
I am successful in getting image urls , my problem is how to download image from the url and show it in a imageview. The code for fetching the url is below.
if((xpp_name.equals("content")))
{
xpp.next();
strvalue=xpp.getText();
if(strvalue!=null){
String url = strvalue.substring(
strvalue.indexOf("src")+5,, strvalue.indexOf("jpg")+3);
arrayList_for_images.add(url);
}
xpp.next();
xpp.next();}
Start a new thread for downloading image from Url and set image in imageview in handler.
private Bitmap pop_up_image_bitmap ;
private Handler handler ;
private Runnable r;
new Thread(new Runnable() {
#Override
public void run() {
URL newurl;
try {
newurl = new URL(<Url>);
pop_up_image_bitmap = BitmapFactory.decodeStream(newurl.openConnection() .getInputStream());
handler.post(r);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
Put handler :
handler = new Handler();
r = new Runnable()
{
public void run()
{
if(pop_up_image_bitmap!=null){
imageview.setImageBitmap(pop_up_image_bitmap);
handler.postDelayed(this, 1000);
popUpImageProgressBar.setVisibility(View.INVISIBLE);
}
}
};
handler.postDelayed(r, 1000);
Here you can find a lazy loading library to download images from a URL and show them in a ListView. Also i suggest you to avoid using 3 different Arraylists and use only one ArrayList, instead, with a custom class that is used to store the information of an image(title, date and image url).
EDIT: Here is an example class that holds the information needed for the image:
import java.util.Date;
public class ImageObject {
private String image_name;
private String image_url;
private Date image_date;
public ImageObject() {
}
public ImageObject(String image_name, String image_url, Date image_date) {
this.image_name = image_name;
this.image_url = image_url;
this.image_date = image_date;
}
public void setImageName(String image_name) {
this.image_name = image_name;
}
public void setImageURL(String image_url) {
this.image_url = image_url;
}
public void setImageDate(Date image_date) {
this.image_date = image_date;
}
public String getImageName() {
return this.image_name;
}
public String getImageURL() {
return this.image_url;
}
public Date getImageDate() {
return this.image_date;
}
}
Here is an example usage in witch i initiate a ArrayList with one ImageObject:
ArrayList<ImageObject> data = new ArrayList<ImageObject>();
ImageObject obj = new ImageObject("test.jpg", "www.imageurl.com", new Date());
data.add(obj);
And this is how you retrieve a value from a certain ImageObject object from the ArrayList:
data.get(0).getImageName();
try out this best image loading library ever.
https://github.com/nostra13/Android-Universal-Image-Loader

Categories

Resources