bad bitmap error when setting Uri

后端 未结 6 1736
暗喜
暗喜 2021-02-19 12:00

I would like to make an ImageView display an image on a website. So I create a new ImageView and execute imgView.setImageURI(uri);

When I launch the app the

相关标签:
6条回答
  • 2021-02-19 12:31

    Glide is an awesome library for displaying images!

     Glide.with(context)
                        .load(uri)
                        .into(imageView);
    
    0 讨论(0)
  • 2021-02-19 12:35

    You need to download the image and then set it as bitmap. Here is one of the many examples: http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

    0 讨论(0)
  • 2021-02-19 12:37

    If it's not a content URI, this link may help. It seems to indicate that imgView.setImageURI() should not be used for regular URIs. Copying in the relevant bit:

    Yes, ImageView.setImageURI(ContentURI uri) works, but it is for content URIs particular to the Android platform, not URIs specifying Internet resources. The convention is applied to binary objects (images, for example) which cannot be exposed directly through a ContentProvider's Cursor methods. Instead, a String reference is used to reference a distinct content URI, which can be resolved by a separate query against the content provider. The setImageURI method is simply a wrapper to perform those steps for you.

    I have tested this usage of setImageView, and it does work as expected. For your usage, though, I'd look at BitmapFactory.decodeStream() and URL.openStream().

    Also to make this answer self-contained, the sample code from another post at that link, showing how to do it:

    private Bitmap getImageBitmap(String url) {
        Bitmap bm = null;
        try {
            URL aURL = new URL(url);
            URLConnection conn = aURL.openConnection();
            conn.connect();
            InputStream is = conn.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            bm = BitmapFactory.decodeStream(bis);
            bis.close();
            is.close();
        } catch (IOException e) {
            Log.e(TAG, "Error getting bitmap", e);
        }
        return bm;
    } 
    

    I haven't tested this code, I'm just paranoid and like to ensure SO answers are useful even if every other site on the net disappears :-)

    0 讨论(0)
  • 2021-02-19 12:37

    Use library Picasso

    Manifest

    uses-permission android:name="android.permission.INTERNET"

    build gradle

    implementation 'com.squareup.picasso:picasso:2.71828'

    Activity:

    Picasso.get().load(photoUrl).into(imageView);

    0 讨论(0)
  • 2021-02-19 12:38

    I've wrote a simple AsyncTask, which converts remote HTTPS to local Uri by caching to SD card:

    public class ProfileImageTask extends AsyncTask<String, Void, Uri> {
    
        private boolean enforce = false;
        private IProfileImageTask listener;
        private String fileName = "photo.jpg";
        private String sdPath;
        private String url;
    
        /** Constructor */
        @RequiresPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        public ProfileImageTask(@NonNull Context context, @NonNull String url, @NonNull IProfileImageTask listener) {
            this.sdPath = Environment.getExternalStorageDirectory() + "/" + context.getResources().getString(R.string.app_name) + "/";
            this.listener = listener;
            this.url = url;
        }
    
        @Override
        protected void onPreExecute() {
    
            /* setup destination directory */
            File directory = new File(this.sdPath + "temp");
            if (! directory.exists()) {directory.mkdirs();}
    
            /* setup file name */
            String[] parts = this.url.split("/");
            this.fileName = parts[parts.length - 1];
        }
    
        @Override
        protected Uri doInBackground(String... arguments) {
            File file = new File(this.sdPath + "temp", this.fileName);
            if(file.exists() && this.enforce) {file.delete();}
            if (! file.exists()) {
                try {
                    URLConnection conn = new URL(this.url).openConnection();
                    conn.connect();
                    InputStream in = conn.getInputStream();
                    FileOutputStream out = new FileOutputStream(file);
                    byte[] b = new byte[1024]; int c;
                    while ((c = in.read(b)) != -1) {out.write(b, 0, c);}
                    out.close();
                    in.close();
                } catch (IOException e) {
                    Log.e("ProfileImageTask", e.getMessage());
                }
            }    
            return Uri.fromFile(file);
        }
    
        @Override
        protected void onPostExecute(Uri uri) {
            if (listener != null && uri != null) {
                this.listener.OnImageAvailable(uri);
            }
        }
    }
    

    The interface:

    public interface IProfileImageTask {
        void OnImageAvailable(@NonNull Uri uri);    
    }
    

    And the implementation:

    @Override
    public void OnImageAvailable(@NonNull Uri uri) {
        this.photoUrl.setImageURI(uri);
    }
    

    Tested with url alike https://lh3.googleusercontent.com/.../photo.jpg (which has about 179kb). One could still downscale larger images, render a set of thumbnails or pass the intended size.

    0 讨论(0)
  • 2021-02-19 12:42

    First, you should download the image and save it in your device(sdcard or memory). Then, get its file path, using Uri.parse(filePath) to convert path to uri finally, call ImageView's setImageURI(Uri) to fullfill. -- I use this way to achieve my purpose and there is a bug:if the image is to large(maybe exceed 1Mb or so, it may report outOfMemeroy Exception!!!)

    0 讨论(0)
提交回复
热议问题