在Android中从url下载图像的最佳方法

时间:2013-08-13 13:38:49

标签: android

我正在使用以下方法从网址下载单张图片

public static Bitmap getBitmap(String url) {
    try {
        InputStream is = (InputStream) new URL(url).getContent();
        Bitmap d = BitmapFactory.decodeStream(is);
        is.close();
        return d;
    } catch (Exception e) {
        return null;
    }
}

有时我会得到一个例外情况。

我无法捕捉到内存异常。该应用程序将关闭。怎么预防这个?

是否有更好的下载图像的方法更快?

13 个答案:

答案 0 :(得分:34)

尝试使用它:

public Bitmap getBitmapFromURL(String src) {
    try {
        java.net.URL url = new java.net.URL(src);
        HttpURLConnection connection = (HttpURLConnection) url
                .openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

对于OutOfMemory问题:

 public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
    int width = bm.getWidth();
    int height = bm.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // CREATE A MATRIX FOR THE MANIPULATION
    Matrix matrix = new Matrix();
    // RESIZE THE BIT MAP
    matrix.postScale(scaleWidth, scaleHeight);

    // "RECREATE" THE NEW BITMAP
    Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
            matrix, false);

    return resizedBitmap;
}

答案 1 :(得分:17)

我使用this库,当你需要处理大量图像时它真的很棒。它以异步方式下载它们,缓存它们等。

对于OOM例外,使用thisthis类会为我彻底减少它们。

答案 2 :(得分:8)

            public void DownloadImageFromPath(String path){
            InputStream in =null;
            Bitmap bmp=null;
             ImageView iv = (ImageView)findViewById(R.id.img1);
             int responseCode = -1;
            try{

                 URL url = new URL(path);//"http://192.xx.xx.xx/mypath/img1.jpg
                 HttpURLConnection con = (HttpURLConnection)url.openConnection();
                 con.setDoInput(true);
                 con.connect();
                 responseCode = con.getResponseCode();
                 if(responseCode == HttpURLConnection.HTTP_OK)
                 {
                     //download 
                     in = con.getInputStream();
                     bmp = BitmapFactory.decodeStream(in);
                     in.close();
                     iv.setImageBitmap(bmp);
                 }

            }
            catch(Exception ex){
                Log.e("Exception",ex.toString());
            }
        }

答案 3 :(得分:4)

您可以按Asyn task下载图片 使用这个类:

public class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> {

private final WeakReference<ImageView> imageViewReference;
private final MemoryCache memoryCache;
private final BrandItem brandCatogiriesItem;
private Context context;
private String url;

public ImageDownloaderTask(ImageView imageView, String url, Context context) {
    imageViewReference = new WeakReference<ImageView>(imageView);
    memoryCache = new MemoryCache();
    brandCatogiriesItem = new BrandItem();
    this.url = url;
    this.context = context;
}

@Override
protected Bitmap doInBackground(String... params) {

    return downloadBitmap(params[0]);
}

@Override
protected void onPostExecute(Bitmap bitmap) {
    if (isCancelled()) {
        bitmap = null;
    }

    if (imageViewReference != null) {
        ImageView imageView = imageViewReference.get();
        if (imageView != null) {
            if (bitmap != null) {
                memoryCache.put("1", bitmap);
                brandCatogiriesItem.setUrl(url);
                brandCatogiriesItem.setThumb(bitmap);
                // BrandCatogiriesItem.saveLocalBrandOrCatogiries(context, brandCatogiriesItem);
                imageView.setImageBitmap(bitmap);
            } else {
                Drawable placeholder = imageView.getContext().getResources().getDrawable(R.drawable.placeholder);
                imageView.setImageDrawable(placeholder);
            }
        }

    }
}

private Bitmap downloadBitmap(String url) {
    HttpURLConnection urlConnection = null;
    try {
        URL uri = new URL(url);
        urlConnection = (HttpURLConnection) uri.openConnection();

        int statusCode = urlConnection.getResponseCode();
        if (statusCode != HttpStatus.SC_OK) {
            return null;
        }

        InputStream inputStream = urlConnection.getInputStream();
        if (inputStream != null) {

            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            return bitmap;
        }
    } catch (Exception e) {
        Log.d("URLCONNECTIONERROR", e.toString());
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
        Log.w("ImageDownloader", "Error downloading image from " + url);
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect();

        }
    }
    return null;
}

}

并将其称为:

  new ImageDownloaderTask(thumbImage, item.thumbnail, context).execute(item.thumbnail);

答案 4 :(得分:3)

我建议使用altex-image-downloader库,该库可以轻松下载图像:

AltexImageDownloader.writeToDisk(context, Imageurl, "IMAGES");

在应用程序构建包中添加依赖项:

implementation 'com.artjimlop:altex-image-downloader:0.0.4'

答案 5 :(得分:2)

遵循load large bitmap的官方指南可以避免OOM例外。

不要在UI线程上运行代码。请改用AsyncTask,你应该没问题。

答案 6 :(得分:2)

您可以使用以下功能从网址下载图片。

private Bitmap getImage(String imageUrl, int desiredWidth, int desiredHeight)
    {   
           private Bitmap image = null;
           int inSampleSize = 0;


            BitmapFactory.Options options = new BitmapFactory.Options();

            options.inJustDecodeBounds = true;

            options.inSampleSize = inSampleSize;

            try
            {
                URL url = new URL(imageUrl);

                HttpURLConnection connection = (HttpURLConnection)url.openConnection();

                InputStream stream = connection.getInputStream();

                image = BitmapFactory.decodeStream(stream, null, options);

                int imageWidth = options.outWidth;

                int imageHeight = options.outHeight;

                if(imageWidth > desiredWidth || imageHeight > desiredHeight)
                {   
                    System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight);

                    inSampleSize = inSampleSize + 2;

                    getImage(imageUrl);
                }
                else
                {   
                    options.inJustDecodeBounds = false;

                    connection = (HttpURLConnection)url.openConnection();

                    stream = connection.getInputStream();

                    image = BitmapFactory.decodeStream(stream, null, options);

                    return image;
                }
            }

            catch(Exception e)
            {
                Log.e("getImage", e.toString());
            }

        return image;
    }

查看完整说明here

答案 7 :(得分:2)

  

将Android网络依赖项添加到项目中

编译'com.amitshekhar.android:android-networking:1.0.0'

    String url = "http://ichef.bbci.co.uk/onesport/cps/480/cpsprodpb/11136/production/_95324996_defoe_rex.jpg";
    File file;
    String dirPath, fileName;
    Button downldImg;

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

        // Initialization Of DownLoad Button
        downldImg = (Button) findViewById(R.id.DownloadButton);

        // Initialization Of DownLoad Button
        AndroidNetworking.initialize(getApplicationContext());

        //Folder Creating Into Phone Storage
        dirPath = Environment.getExternalStorageDirectory() + "/Image";

        fileName = "image.jpeg";

        //file Creating With Folder & Fle Name
        file = new File(dirPath, fileName);

        //Click Listener For DownLoad Button
        downldImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                AndroidNetworking.download(url, dirPath, fileName)
                        .build()
                        .startDownload(new DownloadListener() {
                            @Override
                            public void onDownloadComplete() {

                                Toast.makeText(MainActivity.this, "DownLoad Complete", Toast.LENGTH_SHORT).show();
                            }

                            @Override
                            public void onError(ANError anError) {

                            }
                        });
            }
        });
    }
}
  

运行此代码后   检查手机内存   你可以看到一个文件夹 - 图像   检查此文件夹内,您看到一个名称为“image.jpeg”的图像文件

谢谢!!!

答案 8 :(得分:2)

public class testCrop extends AppCompatActivity {
    ImageView iv;
    String imagePath = "https://style.pk/wp-content/uploads/2015/07/omer-Shahzad-performed-umrah-600x548.jpg";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.testcrpop);
        iv = (ImageView) findViewById(R.id.testCrop);
        imageDownload image = new imageDownload(testCrop.this, iv);
        image.execute(imagePath);
    }

    class imageDownload extends AsyncTask<String, Integer, Bitmap> {
        Context context;
        ImageView imageView;
        Bitmap bitmap;
        InputStream in = null;
        int responseCode = -1;
//constructor.
        public imageDownload(Context context, ImageView imageView) {
            this.context = context;
            this.imageView = imageView;
        }
        @Override
        protected void onPreExecute() {


        }
        @Override
        protected Bitmap doInBackground(String... params) {

            URL url = null;
            try {
                url = new URL(params[0]);

                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                httpURLConnection.setDoOutput(true);
                httpURLConnection.connect();
                responseCode = httpURLConnection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    in = httpURLConnection.getInputStream();
                    bitmap = BitmapFactory.decodeStream(in);
                    in.close();
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bitmap;
        }
        @Override
        protected void onPostExecute(Bitmap data) {
            imageView.setImageBitmap(data);
        }
    }
}

<强>输出

enter image description here

答案 9 :(得分:1)

第1步:在Android清单中声明权限

在第一个Android项目中要做的第一件事是,在“ AndroidManifest.xml”文件中声明所需的权限。

对于Android从URL下载图像,我们需要访问互联网才能下载文件并读写内部存储以将图像保存到内部存储的权限。

在AndroidManifest.xml文件的标签顶部添加以下代码行:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

第2步:向用户请求所需的权限

Android允许每个应用程序在沙箱中运行。如果应用程序需要访问该沙箱外部的某些资源或信息,则需要向用户请求权限。

从Android 6.0开始,Google希望开发人员从应用程序内向用户请求权限,有关权限的更多详细信息,请阅读此内容。

因此,对于Android从URL下载图像,您需要请求读取存储和写入

为此,我们将使用以下代码行来首先检查用户是否已授予了所需的权限,否则,我们将请求存储读取和写入权限。

我们正在创建“下载图像”方法,您可以在需要下载图像的任何地方简单地调用它。

void DownloadImage(String ImageUrl) {

    if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
            ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 123);
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);
        showToast("Need Permission to access storage for Downloading Image");
    } else {
        showToast("Downloading Image...");
       //Asynctask to create a thread to downlaod image in the background 
        new DownloadsImage().execute(ImageUrl);
    }
}

现在,我们已请求并被授予用户权限,以从url下载android下载图像开始,我们将创建一个AsyncTask,因为不允许您在主线程中运行后台进程。

class DownloadsImage extends AsyncTask<String, Void,Void>{

    @Override
    protected Void doInBackground(String... strings) {
        URL url = null;
        try {
            url = new URL(strings[0]);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        Bitmap bm = null;
        try {
            bm =    BitmapFactory.decodeStream(url.openConnection().getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }

        //Create Path to save Image
        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES+ "/AndroidDvlpr"); //Creates app specific folder

        if(!path.exists()) {
            path.mkdirs();
        }

        File imageFile = new File(path, String.valueOf(System.currentTimeMillis())+".png"); // Imagename.png
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(imageFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try{
            bm.compress(Bitmap.CompressFormat.PNG, 100, out); // Compress Image
            out.flush();
            out.close();
            // Tell the media scanner about the new file so that it is
            // immediately available to the user.
            MediaScannerConnection.scanFile(MainActivity.this,new String[] { imageFile.getAbsolutePath() }, null,new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) {
                    // Log.i("ExternalStorage", "Scanned " + path + ":");
                    //    Log.i("ExternalStorage", "-> uri=" + uri);
                }
            });
        } catch(Exception e) {
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        showToast("Image Saved!");
    }
}

在上面的代码行中,使用BitmapFactory.decodeStream创建URL和Bitmap,下载文件。

创建文件路径以保存图像(我们在DIRECTORY_PICTURES中创建了一个名为“ AndroidDvlpr”的文件夹),并初始化了下载。

下载文件MediaScannerConnection之后,将调用该文件以读取文件中的元数据并将文件添加到媒体内容提供者,以便用户可以使用该图像。

在上面的代码行中,我们还创建了一个方法showToast()来显示Toast。完整的代码在这里:

void showToast(String msg){
Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
}

Read more here

答案 10 :(得分:1)

Android清单中的首次声明权限:-

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

MainActivityForDownloadImages.java

public class MainActivityForDownloadImages extends AppCompatActivity {


//    String urls = "https://stimg.cardekho.com/images/carexteriorimages/930x620/Kia/Kia-Seltos/6232/1562746799300/front-left-side-47.jpg";
    String urls = "https://images5.alphacoders.com/609/609173.jpg";
    Button button;
     public final Context context = this;
    ProgressDialog progressDialog ;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_for_download_images);
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
        }


        progressDialog = new ProgressDialog(context);
        button = findViewById(R.id.downloadImagebtn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // initialize the progress dialog like in the first example
                // this is how you fire the downloader

                Intent intent = new Intent(context, DownloadService.class);
                intent.putExtra("url", urls);
                intent.putExtra("receiver", new DownloadReceiver(new Handler()));
                startService(intent);


            }
        });


    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == 0) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED) {


            }
        }
    }

    private class DownloadReceiver extends ResultReceiver {

        public DownloadReceiver(Handler handler) {
            super(handler);
        }

        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {

            super.onReceiveResult(resultCode, resultData);

            if (resultCode == DownloadService.UPDATE_PROGRESS) {

                int progress = resultData.getInt("progress"); //get the progress
                progressDialog.setProgress(progress);
                progressDialog.setMessage("Images Is Downloading");
                progressDialog.show();

                if (progress == 100) {

                    progressDialog.dismiss();

                }
            }
        }
    }

}

DownloadService.java

public class DownloadService extends IntentService {

public static final int UPDATE_PROGRESS = 8344;
String folder_main = "ImagesFolder";


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


@Override
protected void onHandleIntent(Intent intent) {

    String urlToDownload = intent.getStringExtra("url");
    ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");

    try {

        //create url and connect
        URL url = new URL(urlToDownload);
        URLConnection connection = url.openConnection();
        connection.connect();

        // this will be useful so that you can show a typical 0-100% progress bar
        int fileLength = connection.getContentLength();

        // download the file
        InputStream input = new BufferedInputStream(connection.getInputStream());


        File outerFolder = new File(Environment.getExternalStorageDirectory(), folder_main);
        File inerDire = new File(outerFolder.getAbsoluteFile(), System.currentTimeMillis() + ".jpg");


        if (!outerFolder.exists()) {
            outerFolder.mkdirs();
        }

        inerDire.createNewFile();


        FileOutputStream output = new FileOutputStream(inerDire);

        byte data[] = new byte[1024];
        long total = 0;
        int count;
        while ((count = input.read(data)) != -1) {
            total += count;

            // publishing the progress....
            Bundle resultData = new Bundle();
            resultData.putInt("progress", (int) (total * 100 / fileLength));
            receiver.send(UPDATE_PROGRESS, resultData);
            output.write(data, 0, count);
        }

        // close streams
        output.flush();
        output.close();
        input.close();

    } catch (IOException e) {
        e.printStackTrace();

    }

    Bundle resultData = new Bundle();
    resultData.putInt("progress", 100);

    receiver.send(UPDATE_PROGRESS, resultData);
}

}

答案 11 :(得分:0)

我仍在学习Android,因此我无法提供丰富的上下文或提出建议的理由,但这就是我用来从https和本地url检索文件的原因。我在onActivity结果(用于拍照和从图库中选择)中以及在AsyncTask中检索https url时都使用了它。

Func

答案 12 :(得分:0)

从Android中的url下载图像的最佳方法

尝试此代码

DownloadManager downloadManager = (DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE); Uri uri = Uri.parse(imageName); DownloadManager.Request request = new DownloadManager.Request(uri); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); Long reference = downloadManager.enqueue(request);