1

I am trying to display an image from a specific URL to an imageview inside my Android app. I am trying to use the answer available for this question here but I am facing a silly error in my code:

public static Drawable LoadImageFromWebOperations(String url) {
try {
    InputStream ss = (InputStream) new URL(url).getContent(); // here is the error saying that "There is no argument given that corresponds to the required formal parameter 'types' of 'URL.GetContent(Class [])"
    Drawable d = Drawable.createFromStream(ss, "src name"); // and another error here saying: Cannot convert from 'Java.IO.InputStream' to 'System.IO.Stream'
    return d;
} catch (Exception e) {
    return null;
}
}

First error: "There is no argument given that corresponds to the required formal parameter 'types' of 'URL.GetContent(Class [])"

Second error: "Cannot convert from 'Java.IO.InputStream' to 'System.IO.Stream'"

So I searched for another solution and I found this one:

URL url = new URL("http://image10.bizrate-images.com/resizesq=60&uid=2216744464");
Bitmap bmp = 
BitmapFactory.decodeStream(url.openConnection().getInputStream());
imageView.setImageBitmap(bmp);

But also I am getting errors with openconnection() and getInputStream. Please tell me how can I solve my problem or if you have another solution specific for c# users let me know.

Note: I am working with c# in visual studio.

Thank you

3 Answers3

0

Use Glide :

GlideApp
    .with(this)
    .load("http://image10.bizrate-images.com/resizesq=60&uid=2216744464")
    .into(imageView);

Glide is a fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.

Omar Aflak
  • 2,918
  • 21
  • 39
  • I have tried to use it, I am getting an error: Glide doesn't exist in the current context. Do I have to download some libraries ? – Wassim Dernayka Sep 24 '17 at 16:43
  • Yes, add these lines in your gradle dependencies : `compile 'com.github.bumptech.glide:glide:4.1.1' annotationProcessor 'com.github.bumptech.glide:compiler:4.1.1'` – Omar Aflak Sep 24 '17 at 16:54
  • I am using xamarin in visual studio, there aren't gradle dependencies. So I have downloaded Xamarin.Gradle from nuget, now I am getting this [error](https://drive.google.com/file/d/0BwKaqaO9u5AwVnpBREQzWi1qNlE/view?usp=sharing). – Wassim Dernayka Sep 24 '17 at 17:06
0

Quickest Approach:

You can try either of these image downloading library for Android - Picasso or Glide. You can use either one in your Fragment or your Activity or your Adapter:

Picasso:

// .with() only takes Context objects
Picasso.with(context)
       .load("http://image10.bizrate-images.com/resizesq=60&uid=2216744464")
       .into(imageView);

Glide:

// .with() can take Context, Activity, Fragment or FragmentActivity objects.
Glide.with(context)
       .load("http://image10.bizrate-images.com/resizesq=60&uid=2216744464")
       .into(imageView);

Here's a link that explains the similarities and differences between both libraries.


Another Approach:

It involves creating a Service to fetch the data (on a background thread), saving the url into a bitmap and finally sending that bitmap back to the UI thread to be saved in the ImageView.

Steps:

  • Create a Service (and add to the manifest).
  • Service should extend IntentService (and implement onHandleIntent).
  • Retrieve url from intent.
  • Fetch image from url.
  • Decode and save the url to a Bitmap.
  • Put the Bitmap inside an EventBus to send to the UI thread.
  • Set Bitmap to ImageView.

Manifest:

<application
    ...

    <activity android:name=".MainActivity">
        ...
    </activity>

    <service android:name=".ImageFetchService" />

</application>

Eventbus dependency (gradle for Android Studio, Naxam-EventBus.Droid for Visual Studio):

dependencies {
    //
    compile 'org.greenrobot:eventbus:3.0.0'
}

Install-Package Naxam.EventBus.Droid // Use this instead since Xamarin.Android doesn't have gradle.

Service Class:

public class ImageFetchService extends IntentService {

    public ImageFetchService() {
        super("ImageFetchService");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        String urlString = intent.getData().toString();

        URL url;

        try {
            url = new URL(urlString);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            InputStream input = connection.getInputStream();
            Bitmap myBitmap = BitmapFactory.decodeStream(input);

            BitmapEvent bitmapEvent = new BitmapEvent();
            bitmapEvent.setBitmap(myBitmap);
            EventBus.getDefault().post(bitmapEvent);
        } catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }
}

Now, we need a class that will encapsulate the bitmap object sent from our Service class. EventBus transmits objects also known as events and those events can contain any number of other objects inside it - think of an EventBus as a bus that transports a POJO (or event) from one place to another.

In this case, the EventBus will transport our Bitmap from the background thread to the UI thread.

BitmapEvent Class (our POJO for EventBus):

public class BitmapEvent {

    private Bitmap bitmap;

    public BitmapEvent() {
        //
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }
}

MainActivity:

public class MainActivity extends AppCompatActivity {

    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.image);

        String urlString = "http://image10.bizrate-images.com/resizesq=60&uid=2216744464";

        Intent fetchImageIntent = new Intent(this, ImageFetchService.class);
        fetchImageIntent.setData(Uri.parse(urlString));
        startService(fetchImageIntent);
    }

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void getBitmapEvent(BitmapEvent bitmapEvent) {
        imageView.setImageBitmap(bitmapEvent.getBitmap());
    }
}

Note: Depending on your internet connection and the size of the image, you may notice some delay before getting the ImageView to update with the bitmap.

You can look into AsyncTask as an alternative to EventBus.

Community
  • 1
  • 1
chornge
  • 2,021
  • 3
  • 28
  • 37
  • I am getting this error with Glide [error](https://drive.google.com/file/d/0BwKaqaO9u5AwVnpBREQzWi1qNlE/view?usp=sharing). And with picasso I am getting the error saying that I have to use okhttp and okhttp.urlconnection but when I use them I get this error; _java.lang.IllegalArgumentException: already added : Lcom/squareup/okhttp/Address_,and this one; _'Resource.Designer.cs' because it is being used by another process_. What I do ? – Wassim Dernayka Sep 24 '17 at 19:11
  • for the issue with glide, download the Glide.Xamarin nuget library and then try adding the following dependencies: Xamarin.Android.Support.Annotations (>= 25.4.0.2) and Xamarin.Android.Support.v4 (>= 25.4.0.2) – chornge Sep 24 '17 at 19:25
  • I have the Xamarin.Android.Support.v4 downloaded and I have tried to dowload the second one but I got this error: _Could not install package 'Xamarin.Android.Support.Annotations 25.4.0.2'. You are trying to install this package into a project that targets 'MonoAndroid,Version=v6.0', but the package does not contain any assembly references or content files that are compatible with that framework_ – Wassim Dernayka Sep 24 '17 at 19:30
  • it might only be supported on Android 7.0 and up, is it possible to try making your app's target framework set to Android 7.0 (API Level 24) or higher? if it's possible, try installing 7.0 SDK (MonoAndroid70) and setting compilation to the latest version (or to 7.0). – chornge Sep 24 '17 at 19:33
  • Well I successfully downloaded it but I am still getting this error: _java.lang.IllegalArgumentException: already added : Lcom/squareup/okhttp/Address_ – Wassim Dernayka Sep 24 '17 at 20:03
  • do you have okhttp or modernhttp client or retrofit as a dependency? because something in your list of dependencies is using it. try not to use picasso and glide together, use glide and take out any references to picasso (the glide library does not have a dependency with okhttp but picasso does). – chornge Sep 24 '17 at 20:15
  • I am using xamarin in visual studio, there aren't gradle dependencies. I am not using glide an Picasso together. I have tried to use glide after removing all reference related to picasso, the error I am getting: [here](https://drive.google.com/file/d/0BwKaqaO9u5AwVnpBREQzWi1qNlE/view?usp=sharing) – Wassim Dernayka Sep 24 '17 at 20:25
  • from what i can tell from the error in the image, the issue is the 'Glide.With(this)' part. try Glide.With(getActivity()) or Glide.With(getContext()), also other possible issue: the caller and reference projects don't have the same target framework. An example would be a caller project that has .Net 4.5 , but the reference library has target 4.6.1. Make sure that all Glide references are using the same target number. – chornge Sep 24 '17 at 20:35
  • here's a link that may prove helpful with that error: https://stackoverflow.com/questions/20660999/the-type-is-defined-in-an-assembly-that-is-not-referenced-how-to-find-the-cause – chornge Sep 24 '17 at 20:39
  • i have made an edit to include another approach - try again and see if that solves the issue – chornge Oct 06 '17 at 04:08
0

If you want the smaller app and you require very fewer features in the image loading, then Picasso is best. But If you want more customization, animated GIF support, and very better memory management, then you can go ahead with Glide library.

here is code for both.

For Picasso :

 Picasso.with(context)
 .load(url)
 .centerCrop()
 .placeholder(R.drawable.loading_spinner)
 .into(myImageView);

For Glide

Glide.with(context)
.load(url)
.centerCrop()
.placeholder(R.drawable.loading_spinner)
.crossFade()
.into(myImageView);
NipunPerfect
  • 125
  • 1
  • 7