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

RVG*_*RVG 44 android

我正在使用以下方法从url下载单个图像

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

有时我会得到一个outofmemory异常.

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

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

Piy*_*ush 37

试着用这个:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

对于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;
}
Run Code Online (Sandbox Code Playgroud)


asc*_*sco 17

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

至于OOM例外,使用这个这个类大大减少了它们.


小智 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());
            }
        }
Run Code Online (Sandbox Code Playgroud)


小智 6

将此 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) {

                            }
                        });
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢你 !!!


Joh*_*ith 5

您可以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;
}
Run Code Online (Sandbox Code Playgroud)

}

并这样称呼:

  new ImageDownloaderTask(thumbImage, item.thumbnail, context).execute(item.thumbnail);
Run Code Online (Sandbox Code Playgroud)


小智 5

第 1 步:在 Android Manifest 中声明权限

在您的第一个 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" />
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

为此,我们将使用以下代码行首先检查用户是否已授予所需的权限,如果没有,我们将请求存储读写权限。

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们已经请求并获得了用户权限,开始从 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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

void showToast(String msg){
Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
}
Run Code Online (Sandbox Code Playgroud)

在这里阅读更多


gru*_*unk 3

按照官方指南加载大位图可以避免 OOM 异常。

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