57

我正在使用以下方法从 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;
    }
}

有时我会遇到内存不足异常。

我无法捕获内存不足异常。该应用程序将关闭。如何防止这种情况?

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

4

14 回答 14

42

尝试使用这个:

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;
}
于 2013-08-13T13:59:21.937 回答
19

我使用这个库,当你必须处理大量图像时,它真的很棒。它异步下载它们,缓存它们等。

至于 OOM 异常,使用这个这个类对我来说大大减少了它们。

于 2013-08-13T13:42:23.083 回答
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());
            }
        }
于 2013-11-27T10:16:08.447 回答
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) {

                            }
                        });
            }
        });
    }
}

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

谢谢你 !!!

于 2017-03-27T09:43:55.697 回答
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;
    }
}

并称其为:

new ImageDownloaderTask(thumbImage, item.thumbnail, context).execute(item.thumbnail);
于 2015-10-07T04:44:26.547 回答
5

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

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

对于 Android 从 URL 下载图像,我们需要访问 Internet 以下载文件并读取和写入内部存储以将图像保存到内部存储的权限。

在 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 开始,谷歌希望开发人员在应用程序内向用户请求权限,有关权限的更多详细信息请阅读此内容。

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

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

我们正在创建一个方法“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);
    }
}

现在我们已经请求并被授予用户权限,从 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!");
    }
}

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

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

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

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

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

在这里阅读更多

于 2019-03-13T09:32:53.317 回答
3

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

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

于 2013-08-13T13:47:11.917 回答
3

您可以使用以下功能从 url 下载图像。

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;
    }

在此处查看完整说明

于 2014-05-06T07:10:00.540 回答
3

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

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

在 app build gradle 中添加依赖:

implementation 'com.artjimlop:altex-image-downloader:0.0.4'
于 2020-01-07T18:03:38.627 回答
1

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

InputStream input = new URL("your_url_string").openStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
于 2018-07-10T18:12:03.067 回答
1

在 Android Manifest 中首先声明权限:-

<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();

                }
            }
        }
    }

}

下载服务.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);
}

}
于 2019-08-20T13:05:52.510 回答
1
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);
        }
    }
}

输出

在此处输入图像描述

于 2017-09-28T14:09:59.800 回答
0

您可以使用此功能将您的位图/图像保存在所有 android 版本(包括 Android 11)的图库中

private fun addImageToGallery(fileName: String, bitmap: Bitmap, ctx: Context) {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

                val fos: OutputStream
                val resolver = contentResolver
                val values = ContentValues()

                values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
                values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
                values.put(
                    MediaStore.MediaColumns.RELATIVE_PATH,
                    Environment.DIRECTORY_PICTURES + File.separator + "EduImages"
                )

                val imageUri = resolver.insert(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    values
                )
                fos = resolver.openOutputStream(imageUri!!) as OutputStream
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
                fos.close()
                Toast.makeText(
                    ctx, "Saved in gallery",
                    Toast.LENGTH_SHORT
                ).show()

            } else {
                val values = ContentValues()
                values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
                values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, fileName)
                values.put(MediaStore.Images.ImageColumns.TITLE, fileName)

                val uri: Uri? = ctx.contentResolver.insert(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    values
                )
                uri?.let {
                    ctx.contentResolver.openOutputStream(uri)?.let { stream ->
                        val oStream =
                            BufferedOutputStream(stream)
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, oStream)
                        oStream.close()
                        Toast.makeText(ctx, "Saved in gallery", Toast.LENGTH_SHORT)
                            .show()
                    }
                }
            }
        } catch (e: Exception) {
            Toast.makeText(ctx, e.localizedMessage, Toast.LENGTH_SHORT).show()
        }
    }
于 2021-09-01T12:57:49.153 回答
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);
于 2019-10-22T10:34:32.707 回答