如何使用 Https URL 从服务器 (Amazon S3) 在 android 中加载图像?

How to load image in android from server(Amazon S3) with Https URL?

我是 android 的初学者。 我正在处理客户端代码,我必须读取存储在服务器上的图像并将其显示在图像视图中。 我参考了一些 Whosebug 问题但无法成功。 我用 HttpsURLConnection class 做了简单的纯 java 程序,我从服务器得到了一些二进制响应,用纯 java 代码就可以了。 但是,当我在 android 中尝试同样的事情并稍微更改代码时,我得到了异常:

01-29 18:39:28.199: WARN/System.err(2045): java.io.IOException: SSL handshake failure: I/O error during system call, Unknown error: 0
01-29 18:39:28.249: WARN/System.err(2045):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeconnect(Native Method)
01-29 18:39:28.249: WARN/System.err(2045):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:316)
01-29 18:39:28.249: WARN/System.err(2045):     at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.getSecureSocket(HttpConnection.java:168)
01-29 18:39:28.249: WARN/System.err(2045):     at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:399)

这是我的 public URL 示例图片:

https://s3-ap-southeast-1.amazonaws.com/edt-demo-app/app-images/Mobile.jpg

在普通 java 中对我来说工作正常的代码如下:

package com.psl.dao; 
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

mport javax.net.ssl.HttpsURLConnection;

   public class HttpsClient{

   public static void main(String[] args)
   {
        String url = "https://s3-ap-southeast-1.amazonaws.com/edt-demo-app/app-images/Mobile.jpg";
        try {
            new HttpsClient().print(url);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   
   }


   public void print(String url)throws Exception
   {
     String httpsURL = url;
     URL myurl = new URL(httpsURL);



     System.setProperty("https.proxyHost", "puproxy.company.co.in");
     System.setProperty("https.proxyPort", "8080");

     HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
     System.out.println(con.toString());
     InputStream ins = con.getInputStream();
     InputStreamReader isr = new InputStreamReader(ins);
     BufferedReader in = new BufferedReader(isr);

     String inputLine;

     while ((inputLine = in.readLine()) != null)
     {
       System.out.println(inputLine);
     }

     in.close();
   }    
}

然后我参考了一些 android 教程并在我的 android 应用程序中尝试了以下代码:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class TestSSL {

    public static void main(String[] args) throws Exception {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } };
        // Install the all-trusting trust manager
        final SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };


        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

        System.setProperty("https.proxyHost", "puproxy.company.co.in");
       System.setProperty("https.proxyPort", "8080");

        URL url = new URL("https://s3-ap-southeast-1.amazonaws.com/edt-demo-app/app-images/Mobile.jpg");
        URLConnection con = url.openConnection();
        final Reader reader = new InputStreamReader(con.getInputStream());
        final BufferedReader br = new BufferedReader(reader);        
        String line = "";
        while ((line = br.readLine()) != null) {
            Log.d("tag",line+"");
        }        
        br.close();
    } // End of main 
} // End of the class //

但是我得到了上面所说的异常:

01-29 18:39:28.199: WARN/System.err(2045): java.io.IOException: SSL handshake failure: I/O error during system call, Unknown error: 0

欢迎任何其他通过使用图像异步加载与 Apache HttpClient 或异步 HttP 客户端库一起正常工作的代码。 我也不知道如何在 android 中进行代理设置。所以请用相应的参数为我做这件事

我尝试了以下教程,但我的图像没有显示。

http://javatechig.com/android/download-image-using-asynctask-in-android

以上教程适用于 Http URL 但不适用于 Https

我想要像上面教程中那样适用于 HTTPS 的代码URL暂时考虑服务器证书对我来说并不重要。

试试这个代码...

             try  
             { 
                  InputStream imageURL = new URL (url).openStream();  
                  bitmap = BitmapFactory.decodeStream(imageURL);   
             } 
             catch (Exception e) 
             { 
                 e.printStackTrace();
             }  

最佳解决方案是 Android-Universal-Image-Loader,使用起来非常简单

请试试这个代码

  • 主要活动
  package com.example.androidhttpsdemo;

  /*
   * 
   * MainActivity.java
   * @author Santosh Shinde
   * Date: 30/01/2015 12:28:16 PM
   * 
   */
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.URL;
  import java.net.URLConnection;

  import javax.net.ssl.HttpsURLConnection;

  import android.app.Activity;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.widget.ImageView;

  public class MainActivity extends Activity {
      //public static final String URL  ="https://googledrive.com/host/0B_DiX4MiMa3HTHdiYVRmUHBMcW8/image1.jpg";
      public static final String URL="https://s3-ap-southeast-1.amazonaws.com/edt-demo-app/app-images/Mobile.jpg";
      ImageView imageView;

      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          imageView = (ImageView) findViewById(R.id.ImageView1);

          // Create an object for subclass of AsyncTask
          GetXMLTask task = new GetXMLTask();
          // Execute the task
          task.execute(new String[] { URL });
      }

      private class GetXMLTask extends AsyncTask {
          @Override
          protected Bitmap doInBackground(String... urls) {
              Bitmap map = null;
              for (String url : urls) {
                  map = downloadImage(url);
              }
              return map;
          }

          // Sets the Bitmap returned by doInBackground
          @Override
          protected void onPostExecute(Bitmap result) {
              imageView.setImageBitmap(result);
              System.out.println("finished");
          }

          // Creates Bitmap from InputStream and returns it
          private Bitmap downloadImage(String url) {
              Bitmap bitmap = null;
              InputStream stream = null;
              BitmapFactory.Options bmOptions = new BitmapFactory.Options();
              bmOptions.inSampleSize = 1;

              try {
                   stream = getHttpConnection(url);
                   bitmap = BitmapFactory.
                            decodeStream(stream, null, bmOptions);
                   stream.close();
              } catch (IOException e1) {
                   e1.printStackTrace();
              }
              return bitmap;
          }

          // Makes HttpURLConnection and returns InputStream
          private InputStream getHttpConnection(String urlString)
                                              throws IOException {
              InputStream stream = null;
              URL url = new URL(urlString);
              URLConnection connection = url.openConnection();

              try {
                   HttpsURLConnection httpConnection = (HttpsURLConnection) connection;
                   httpConnection.setRequestMethod("GET");
                   httpConnection.connect();

                   if (httpConnection.getResponseCode() == HttpsURLConnection.HTTP_OK ||
                           httpConnection.getResponseCode() == HttpsURLConnection.HTTP_NOT_MODIFIED ) {

                           stream = httpConnection.getInputStream(); 
                   } else { // just in case.. 

                            //log.d("Surprize HTTP status was: " ,httpConnection.getResponseCode()); 
                           } 
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
              return stream;
          }
      }
  }

您只需将 build.gradle 中的 dataBinding 设置为 true 添加 Glide 库即可很好地加载图像

android {
   compileSdkVersion 25
   buildToolsVersion '25.0.3'

   dataBinding {
       enabled = true
   }
...
}

并创建一个 BindingAdapter,这将覆盖当前方法(在本例中 android:src="...") 并加载图像。

@BindingAdapter("android:src")
public static void setImageUrl(ImageView imageView, String url) {
    Context context = imageView.getContext();
    Glide.with(context).load(url).into(imageView);
}

现在你可以简单地在 xml 中传递一个 url 并且它会加载图像,这个方法可以放在代码的任何地方。

<ImageView
  android:id="@+id/status_avatar"
  android:layout_width="64dp"
  android:layout_height="64dp"
  android:src="http://knightwise.com/wp-content/uploads/2014/02/android-apple-wallpaper.jpg"/>