I'm trying to create a simple app that loading photos from a website (like 9gag). I'm using jSoup and asyncTask. The problem is when I'm running the app it shows me only the urls of the images.. what can I do in order to display the image in the listView and not the urls.
XML Prob? Help :-/
![Screen Shot]https://www.dropbox.com/s/moybisjrbdgzjre/Screenshot_2013-04-29-20-09-13.png
here's my LoadImages class:
public LoadImages(ArrayList list, ArrayAdapter adapter)
{
this.list = list;
this.adapter = adapter;
}
#Override
protected Elements doInBackground(String... params) {
org.jsoup.nodes.Document doc = null;
try
{
doc =Jsoup.connect("http://mongol.co.il/").get();
return doc.select("img");
}
catch (IOException e1)
{
e1.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Elements result) {
super.onPostExecute(result);
int flag=0;
//Bitmap bitmap = null;
for ( org.jsoup.nodes.Element div : result )
{
String bla = div.absUrl("src");
list.add(bla);
flag++;
if(flag==3)
break;
}
adapter.notifyDataSetChanged();
}
Here's also my .xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
Thanks In advance!
You're only fetching the URLs at this point. You need to fetch the actual Bitmap data in order to show images. There are two ways to do this:
Download all the images, then show the list after everything is fetched
Show the list immediately with image placeholders, the fetch the images as they're
needed
In general, it's a better experience to respond quickly by showing what you have as you get it (option #2). A ListView is really conducive to this model. In the getView() method of the adapter you'll show the placeholder image while firing off an AsyncTask to get the bitmap. You'll then set Image in onPostExecute. Unfortunately things get messy with View recycling. This basic implementation will result in the wrong image being shown in many cases and a totally unresponsive device if the user scrolls back and forth quickly.
Fortunately, these are problems that others have solved. In fact, there is an excellent set of tutorials along with sample code on Android Developer website.
I have done something like this:
I have a DB with ID, image URL, image URI
image URI is something like file:////mnt/sdcard/<your package>/images/image1.png
I have a place Holder image for each row and in my Arraylist i have put image URI in Arraylist. then in getView method check if that URI file exists or not if not then send a broadcast to download that image(with ID). In downloader I fetch images with corresponding URL.
How to check URI exists: create a file object with URI and call isExists()
How to send broadcast: create an intent put ID in extras then call sendBroadcast(intent)
Now how to refresh list after image has been download: Send another broadcast from onPostExecute() to refresh list and catch that broadcast in your activity and call list.notifyDatasetChanged().
You are adding String to the list
String bla = div.absUrl("src");
list.add(bla);
You need to create custom adapter (for the ListView), which will take that String bla and download the image.
Try this tutorial
Related
public class About extends AppCompatActivity {
ImageView imageView;
TextView textView;
String mediaUrL;
private FirebaseFirestore firebaseFirestore;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
firebaseFirestore = FirebaseFirestore.getInstance();
imageView = findViewById(R.id.showGraphImage);
textView = findViewById(R.id.jkbdsjfdvshf);
firebaseFirestore.collection("crimeData").document("graph").get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot snapshot) {
mediaUrL = snapshot.getString("imageUrl");
textView.setText(mediaUrL);
System.out.println(snapshot.getString("imageUrl"));
}
});
Glide.with(this).load(mediaUrL).into(imageView);
System.out.println(mediaUrL);
I am new to android and I am using Cloud Firestore to store the data online .the variable mediaUrl prints on the console but don't show in the activity. I got the answer but still, now it is not working. Further, I added a used mediaUrl to display the image but it is also not showing on the activity.
As Sahil Goyal wrote, you need to use TextView.
final TextView textView = findViewById<TextView>(R.id.textView);
...
public void onSuccess(DocumentSnapshot snapshot) {
mediaUrL = snapshot.getString("imageUrl")
System.out.println(snapshot.getString("imageUrl"));
textView.setText(mediaUrL);
}
You must have to add an adapter item and initiate that with a template adapter item in order to work with it.
Make a adapter class and inside oninstantiateitem() function create a itemview -
val itemView: View = LayoutInflater.from(container.context).inflate(
R.layout.pageadapteritem, container, false
)
After you have created itemview set -
itemView.textView.setText(mediaUrl)
PS - This code is in Kotlin, kindly change it to java when android studio asks to do so while pasting.
The problem in your code lies in the fact that you are trying to set the image using the following lines of code:
Glide.with(this).load(mediaUrL).into(imageView);
System.out.println(mediaUrL);
Outside the "onSuccess()" callback. Any code that needs data from Cloud Firestore, needs to be inside the onSuccess method, or be called from there. So the simplest solution is to move both lines of code right after:
System.out.println(snapshot.getString("imageUrl"));
This is happening because Firebase API is asynchronous. For more info about this topic, please see my answer from the following post:
How to return a DocumentSnapShot as a result of a method?
If you want to show the image onto the ImageView, you should consider the following first:
1.- Please, double check if the image on your firebase has public access, you can set that permissions from the Google Cloud console through the shell console with this command.
gsutil acl ch -u AllUsers:R gs://<YOUR_BUCKET>/<IMAGE_NAME>
After that, to validate if your image has public access you can copy and paste the url string on a web browser, you must see your image in there.
2.- Also verify, if the path on the code to your image on firebase database has no typos and is correct. After checking the previous, If you see the “imageURL” value is printed on the console.
3.- You should move this line
Glide.with(getApplicationContext()).load(mediaUrl).into(imageView);
inside the onSuccess() method like this:
public void onSuccess(DocumentSnapshot snapshot) {
mediaUrl = snapshot.getString("imageUrl");
textView.setText(mediaUrl);
Glide.with(getApplicationContext()).load(mediaUrl).into(imageView);
}
then it will be set on your imageView.
Good luck!
I was writing an android application which contains a RecyclerView inside my ActivityMain. Each rows has an imageButton and a textLabel. In onBindViewHolder() method, I download an image from an URL and after using setImageDrawable method, I change the image with the one that I just downloaded.
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
holder.textAuthor.setText(posts.get(position).getAuthorName());
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
// Get URL Image from my ArrayList Posts(which contains imageButton and textLabel)
URL url = new URL(posts.get(position).getImageView());
// Get inputStream from URL
InputStream inputStream = (InputStream) url.getContent();
// Create a drawable which contains my downloaded image
Drawable drawable = Drawable.createFromStream(inputStream, null);
// Change the image with the new one
holder.imageButton.setImageDrawable(drawable);
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
All my ImageButton change image correctly downloading from their URL, but the problem is that they have wrong size until I scroll down and after a while I scroll up inside of my RecyclerView using my finger. It sounds like if I have to refresh my View but I don't know how to do this.
Note: all images have different size
I let you some images to explain better my problem:
When I open my application and it starts to download image from URL
When the download is completed the images have wrong size
If I scroll down and after I scroll up I get the images with the correct size
The rest of my codes is here: MainActivty MyAdapter PostClass
XML File which contains ImageButton: my row of RecyclerView
Hope you can help me as always, thank you a lot!
EDIT: I have fixed downloading image using Glide!
Try the following code it worked for me
<ImageButton
android:id="#+id/imageButton2"
android:layout_width="25dp"
android:layout_height="25dp"
app:srcCompat="#drawable/about" />
give your image button fixed height and width then it will work
I'm starting to learn how to build an Android TV for the first time so I apologize for a likely obvious answer to this question. Basically, I'm trying to replicate how the Android TV Youtube App displays when there is no internet connectivity as shown:
YouTube shows the main fragment (I believe) in the back with no videos, and there seems to be a transparent overlay with an ImageView, TextView, and Button. Once there is internet connectivity and the user taps the Retry button, it loads the video content and the overlay disappears.
I'm trying to achieve this exact same technique, and with internet connectivity, I currently have this:
With no internet connectivity, I'd like to show something similar to how YouTube does.
Here's some of my basic code:
MainActivity.java:
public class MainActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_browse_fragment"
android:name="com.ui.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ui.MainActivity"
tools:deviceIds="tv"
tools:ignore="MergeRootFrame" />
MainFragment.java:
public class MainFragment extends DetailsFragment
{
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
setupUIElements();
setupThings();
}
public void setupThings()
{
if (isOnline() == true)
{
prepareBackgroundManager();
loadRows();
setupEventListeners();
}
else
{
// I don't know what to do here???
}
}
public Boolean isOnline()
{
try
{
Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
int returnVal = p1.waitFor();
boolean reachable = (returnVal == 0);
return reachable;
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
Simple, if there's internet connection, I load the videos from online, otherwise, I inform the user like YouTube does.
Where I'm stuck is in the else statement. I'm not sure exactly what to create there to achieve this overlay.
I've looked at some solutions regarding switching fragments here:
Switching between Fragment view
How to switch between fragments during onclick?
However, I'm not sure if, for my purpose, I would need to do this?
Can someone point me in the right direction? I'm not looking to have someone write the whole code exactly like the YouTube app, but I'd like to have a small sample, with just maybe a Button or TextView? This will allow me to follow the structure and modify it to meet my requirements.
Thanks.
You can look at the Leanback Sample app, which contains an example of a BrowseErrorFragment.
To display:
BrowseErrorFragment errorFragment = new BrowseErrorFragment();
getFragmentManager().beginTransaction().replace(R.id.main_frame, errorFragment)
.addToBackStack(null).commit();
I'm attempting parse a JSON payload and place the information in Relative Layout View.
I use this STANDARD asynchronous download routine to obtain the bitmaps to be placed in the appropriate ImageView:
public class AsyncDownloadImage extends AsyncTask<String,Void,Bitmap>{
ImageView bmImage;
public AsyncDownloadImage(ImageView bmImage){
this.bmImage = bmImage;
}
#Override
protected Bitmap doInBackground(String... urls) {
String urldisplay = null;
urldisplay = urls[0];
Bitmap merchViewBitMap = Bitmap.createBitmap(90,90,Bitmap.Config.ARGB_8888);
try{
InputStream in = new URL(urldisplay).openStream();
merchViewBitMap = BitmapFactory.decodeStream(in);
in.close();
}catch(Exception e){
System.out.println(String.format("Image Download Exception ==> %s", e.toString()));
}
return merchViewBitMap;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
bmImage.setImageBitmap(result);
}
}
It's called this way in the getView method of the Adapter class:
String imageUrl = String.format("https://www.xxxxxx.com/va/public/render_image?image_id=%s", currentMerchItem.getMt_image_id());
new AsyncDownloadImage(viewHolder.imageview).execute(imageUrl);
The images are downloaded and the ImageView(s) are set, but they are downloaded repeatedly and infinitely. Multiple images seem to be in an ImageView and when scrolled through they change as each is gif.
How do I stop this after the last image in the list is downloaded?!
-TU
The adapters getView method will be called each time the view of the adapter (listview for example) needs to refresh item's view. When you scroll for example you will get many calls to the getview method (depends on the list length ofcourse). At least you need to manage which images are already being loaded from the net in your case. You also have a lot of open source code for lazy loading exactly for cases like yours.
You can also check this thread, it may help you:
Lazy load of images in ListView
Within my android application, I'm wanting to update an ImageView, with an image specified from a URL. This URL has been fetched via an API as part of an AsyncTask.
I have defined the ImageView as follows:
<ImageView
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:layout_height="wrap_content"
android:id="#+id/product_image"
android:src="#drawable/no_product_image"
android:layout_marginRight="6dip"
android:layout_width="wrap_content"
/>
That way, whilst the data is loading, there is a blank image present behind a ProgressDialog.
As part of the doInBackground of the AsyncTask, after fetching the product details, I call:
private void createProductScreen(Product product){
Log.i(TAG, "Updating product screen");
//Set the product image
ImageView imgView =(ImageView)findViewById(R.id.product_image);
Drawable drawable = loadImageFromWeb(product.getImageUrl());
imgView.setImageDrawable(drawable);
Log.i(TAG, "Set image");
}
The image is loading from the web as follows:
private Drawable loadImageFromWeb(String url){
Log.i(TAG, "Fetching image");
try{
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src");
Log.i(TAG, "Created image from stream");
return d;
}catch (Exception e) {
//TODO handle error
Log.i(TAG, "Error fetching image");
System.out.println("Exc="+e);
return null;
}
}
When this runs I see "Created image from stream" in the log, but don't see "Set image" and the onPostExecute of the AsyncTask is never called.
Does anyone have any ideas on the issue or a better way of updating the image from the blank image to the product image?
You should get an Exception since you are trying to set the ImageView in a separated thread.
imgView.setImageDrawable(drawable); must be called in the same UI thread.
Since you are using the AsyncTask class, the right place for set the imageview object is inside the onPostExecute method.
Change you logic in a way that the doInBackground will returns the Drawable object to the onPostExecute method, then use it calling imgView.setImageDrawable(drawable);
Set Imageview to drawable image
Drawable drawable = loadImageFromWeb(product.getImageUrl());
here is problem.
Drawable drawable = loadImageFromWeb(XXXXUrl);
Imageview.setImageDrawable(drawable);
Give a proper URL to drawable.