如何下载并保存在Android中的图像并保存、图像、如何下载、Android

2023-09-11 11:48:32 作者:要的就是范儿

如何从指定的URL在Android的下载和保存图像?

How do you download and save an image from a given url in Android?

推荐答案

************更新为2015年4月14日 - 库***********************

******************************UPDATE AS OF 14.04.2015 - Libraries ***********************

当然,你可以进行下载并自行管理图像,但如果你的项目是相当复杂的已经有很多图书馆的周围,你并不需要推倒重来。我不会发布code这个时候,因为有很多的例子,但我要告诉你相关的图像下载约2最有用的库(IMO)。

Of course you can perform downloading and managing images by yourself, but if your project is quite complex already, there are a lot of libraries around and you do not need to reinvent the wheel. I won't post code this time since there are a lot of examples, but I'm going to tell you about 2 most useful libraries (IMO) related to image downloading.

1) Android的抽射高出。由谷歌创建和覆盖正式文件强大的网络库。 POST'ing或GET'ing数据,图像,JSON - 凌空抽射将管理它。使用抽射稍稍图像下载是有点在我看来矫枉过正。

1) Android Volley. A powerful networking library created by Google and covered by official documentation. POST'ing or GET'ing data, images, JSON - volley will manage it for you. Using volley just for image downloading is a bit of an overkill in my opinion.

官方消息

非官方镜(每周同步)

凌空行家中央

官方文档

2)的毕加索

图片下载和缓存,完美的的ListView / 的GridView / RecyclerView 。 Apache 2.0许可。

Image downloading and caching, perfect for ListView/GridView/RecyclerView. Apache 2.0 license.

GitHub上

样品

3)壁画

很被Facebook创建了一个新的图像加载库。渐进式JPEG流,GIF和更多。 Apache 2.0的

Quite a new image loading library created by Facebook. Progressive JPEG streaming, gifs and more. Apache 2.0

文档

来源

希望这个信息将是有益的。干杯。

Hope this information will be useful. Cheers.

************ 更新内容2014年7月24日的 ****** *********

**************************** UPDATE AS OF 24.07.2014 ***********************************

由于这个职位已经收到了相当多的关注,我终于找到了建立一个适当的演示项目如下特点时间:

Since this post has received quite a lot of attention, I finally found the time to create a proper demo project with following features:

在UI线程上的图像下载(只用于演示目的,不使用,在实际项目!) 使用后台下载一个的AsyncTask 采用的是Android后台下载下载管理器 保存图像到SD 使用会话饼干 为code忽略SSL错误(学分转到丹尼尔,请参阅original讨论获得更多信息) Image download on UI thread (for demo purposes only, don't use that in real projects!) Background download using an AsyncTask Background download using the Android DownloadManager Saving image to sd Using session Cookie Ignoring SSL errors (credits for that code go to Daniel, please refer to the original discussion for more information)

通过Nexus 5 @ 4.4.4。与往常一样,随意使用这个code出于任何目的,并修改它以任何方式。你可以在这里下载演示项目

Tested on Nexus 5 @4.4.4. As always, feel free to use this code for any purposes and modify it in any way. You can download the demo project here

|***************************************************************************************************|

|***************************************************************************************************|

原code - 注意丑陋的编程 - 参见上面的示例项目

我经常遇到,人们都在问如何从URL下载图像的问题,将其保存等等。所以,我决定发布一个示例项目展示如何做到这一点有两种方法:在主UI线程,并在后台,使用的AsyncTask 类,并显示下载进度。您还可以将图像保存到SD卡。

I often come across questions where people are asking how to download an image from url, save it etc. So I decided to post a sample project showing how to do it in two ways: on the main UI thread and in the background, using the AsyncTask class and showing the download progress. You will also be able to save the image to SD card.

希望这会帮助别人。随意使用这个code作任何用途。也欢迎您来编辑和改善code,如果你认为这可能会做的更好。可以下载完整的项目here(.rar)

Hope this will help someone. Feel free to use this code for any purposes. You are also welcome to edit and improve the code if you think this could be done better. The complete project can be downloaded here(.rar)

P.S。我没有在这里贴上进口

P.S. I did not paste the imports here

修改 几点说明。您可以在主UI线程下载图像(或任何类型的数据),但是这将迫使活动冻结,直到操作完成,这可能是不是你想要的。 的AsyncTask 运行在自己的线程,这意味着你的主线程的用户使用不会受到影响交互。也可以不显示任何进展,在这种情况下,你只需要删除的任何调用 publishProgress()方法和你的类将与<虚空,虚空,虚空> 。 onProgressUpdate()方法也可以被删除的是如​​此。您可以使用的AsyncTask 在后台执行任何操作,然后在你的主UI线程公布结果。

EDIT Some explanations. You can download an image (or any type of data) on your main UI thread, but this would force the Activity to "freeze" until the operation is complete and this is probably not what you want. AsyncTask runs in its own thread which means your main thread the user is interacting with will not be affected. It is also possible to not show any progress, in that case you just need to remove any calls to the publishProgress() method and your class will be parametrized with <Void, Void, Void>. onProgressUpdate() method can also be removed is that case. You can use an AsyncTask to perform any operations in the background and then publish results on your main UI thread.

注意

第1的可能性将不会在Android上工作3及以上的,因为它会导致 NetworkOnMainThreadExeption 。与Android 3.0(蜂巢)开始,你可能无法在没有你的主线程进行网络操作。有一种快速的方法来解决这个问题,只需添加以下code到你的的onCreate()方法来禁用检查(需要API拉特9或以上):

The 1st possibility will NOT work on Android 3 and above, since it will cause the NetworkOnMainThreadExeption. Starting with Android 3.0 (Honeycomb) you may not not perform network operations on your main thread. There is a quick way to solve this, just add the following code to your onCreate() method to disable check (requires API lvl 9 or above):

 StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
 StrictMode.setThreadPolicy(policy);

,将让你的下载工作,虽然我强烈推荐使用 AsyncTasks 后台处理的

That will get your download working, though I strongly recommend using AsyncTasks for background processing

MainActivity.java

    package com.example.stackoverflow.com;
    public class MainActivity extends Activity implements View.OnClickListener {

private Button download, downloadBG, save;
private ImageView img;
private ProgressBar pb;
private EditText etUrl;
private TextView percent;
private ImageDownloader mDownloader;
private static Bitmap bmp;
private FileOutputStream fos;

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

}

/*--- initialize layout components ---*/
private void initViews() {

    download = (Button) findViewById(R.id.btnDownload);
    downloadBG = (Button) findViewById(R.id.btnDownloadBackground);
    save = (Button) findViewById(R.id.btnSave);
    /*--- we are using 'this' because our class implements the OnClickListener ---*/
    download.setOnClickListener(this);
    downloadBG.setOnClickListener(this);
    save.setOnClickListener(this);
    save.setEnabled(false);
    img = (ImageView) findViewById(R.id.image);
    img.setScaleType(ScaleType.CENTER_CROP);
    pb = (ProgressBar) findViewById(R.id.pbDownload);
    pb.setVisibility(View.INVISIBLE);
    etUrl = (EditText) findViewById(R.id.etUrl);
    percent = (TextView) findViewById(R.id.tvPercent);
    percent.setVisibility(View.INVISIBLE);

}

@Override
public void onClick(View v) {
    /*--- determine which button was clicked ---*/
    switch (v.getId()) {

    case R.id.btnDownload:

        /*--- we use trim() to remove whitespaces which could be entered ---*/
        if (etUrl.getText().toString().trim().length() > 0) {
            bmp = ImageDownloader.getBitmapFromURL(etUrl
                    .getText().toString().trim());
            img.setImageBitmap(bmp);
            save.setEnabled(true);
        }

        break;

    case R.id.btnDownloadBackground:

        /*--- check whether there is some Text entered ---*/
        if (etUrl.getText().toString().trim().length() > 0) {
            /*--- instantiate our downloader passing it required components ---*/
            mDownloader = new ImageDownloader(etUrl.getText().toString()
                    .trim(), pb, save, img, percent, MainActivity.this, bmp, new ImageLoaderListener() {
                @Override
                public void onImageDownloaded(Bitmap bmp) {
                    MainActivity.bmp = bmp;
         /*--- here we assign the value of bmp field in our Loader class 
                   * to the bmp field of the current class ---*/    
                }
                });

            /*--- we need to call execute() since nothing will happen otherwise ---*/
            mDownloader.execute();

        }

        break;

    case R.id.btnSave:
        /*--- we do not need to pass our bitmap to this method 
         * since it's our class field and already initialized at this point*/

        saveImageToSD();

        break;

    }

}

private void saveImageToSD() {

    /*--- this method will save your downloaded image to SD card ---*/

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    /*--- you can select your preferred CompressFormat and quality. 
     * I'm going to use JPEG and 100% quality ---*/
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    /*--- create a new file on SD card ---*/
    File file = new File(Environment.getExternalStorageDirectory()
            + File.separator + "myDownloadedImage.jpg");
    try {
        file.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
    /*--- create a new FileOutputStream and write bytes to file ---*/
    try {
        fos = new FileOutputStream(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    try {
        fos.write(bytes.toByteArray());
        fos.close();
        Toast.makeText(this, "Image saved", Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

       }

ImageDownloader.java (后台下载)

 package com.example.stackoverflow.com;


 /*
 * here we are going to use an AsyncTask to download the image 
  *      in background while showing the download progress
  * */

    public class ImageDownloader extends AsyncTask<Void, Integer, Void> {

private ProgressBar pb;
private String url;
private Button save;
private Context c;
private int progress;
private ImageView img;
private Bitmap bmp;
private TextView percent;
private ImageLoaderListener listener;


/*--- constructor ---*/
public ImageDownloader(String url, ProgressBar pb, Button save,
        ImageView img, TextView percent, Context c, Bitmap bmp, ImageLoaderListener listener) {
/*--- we need to pass some objects we are going to work with ---*/
    this.url = url;
    this.pb = pb;
    this.save = save;
    this.c = c;
    this.img = img;
    this.percent = percent;
    this.bmp = bmp;
    this.listener = listener;
}

/*--- we need this interface for keeping the reference to our Bitmap from the MainActivity. 
 *  Otherwise, bmp would be null in our MainActivity*/
public interface ImageLoaderListener {

    void onImageDownloaded(Bitmap bmp);

    }

@Override
protected void onPreExecute() {

    progress = 0;
    pb.setVisibility(View.VISIBLE);
    percent.setVisibility(View.VISIBLE);
    Toast.makeText(c, "starting download", Toast.LENGTH_SHORT).show();

    super.onPreExecute();
}

@Override
protected Void doInBackground(Void... arg0) {

    bmp = getBitmapFromURL(url);

    while (progress < 100) {

        progress += 1;

        publishProgress(progress);

        /*--- an image download usually happens very fast so you would not notice 
         * how the ProgressBar jumps from 0 to 100 percent. You can use the method below 
         * to visually "slow down" the download and see the progress bein updated ---*/

      SystemClock.sleep(200);

    }

    return null;
}

@Override
protected void onProgressUpdate(Integer... values) {

/*--- show download progress on main UI thread---*/
    pb.setProgress(values[0]);
    percent.setText(values[0] + "%");

    super.onProgressUpdate(values);
}

@Override
protected void onPostExecute(Void result) {

    if (listener != null) {
        listener.onImageDownloaded(bmp);
        }
    img.setImageBitmap(bmp);
    save.setEnabled(true);
    Toast.makeText(c, "download complete", Toast.LENGTH_SHORT).show();

    super.onPostExecute(result);
}

public static Bitmap getBitmapFromURL(String link) {
    /*--- this method downloads an Image from the given URL, 
     *  then decodes and returns a Bitmap object
     ---*/
    try {
        URL url = new URL(link);
        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();
        Log.e("getBmpFromUrl error: ", e.getMessage().toString());
        return null;
    }
}

     }

activity_main.xml

              <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="140dp"
        android:layout_height="140dp"
        android:layout_below="@+id/pbDownload"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="23dp"
        android:src="@drawable/default_image" />

    <Button
        android:id="@+id/btnDownload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnDownloadBackground"
        android:layout_alignRight="@+id/btnDownloadBackground"
        android:layout_below="@+id/etUrl"
        android:layout_marginTop="15dp"
        android:text="Download" />

    <Button
        android:id="@+id/btnDownloadBackground"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btnDownload"
        android:layout_centerHorizontal="true"
        android:text="Download in background" />

    <Button
        android:id="@+id/btnSave"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnDownloadBackground"
        android:layout_alignRight="@+id/btnDownloadBackground"
        android:layout_below="@+id/btnDownloadBackground"
        android:text="Save to SD" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:text="How to download an Image"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <ProgressBar
        android:id="@+id/pbDownload"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/image"
        android:layout_alignRight="@+id/image"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="15dp" />

    <EditText
        android:id="@+id/etUrl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/image"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:ems="10"
        android:hint="enter image url" />

    <TextView
        android:id="@+id/tvPercent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/image"
        android:layout_toRightOf="@+id/pbDownload"
        android:text="0%" />
</RelativeLayout>

 </ScrollView>

AndroidManifest.xml中

          <?xml version="1.0" encoding="utf-8"?>

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="10" />

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

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.stackoverflow.com.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
   </application>

  </manifest>