参考:http://m.blog.csdn.net/blog/telenewbie/44815035
问题产生的原因是https网站的证书不是Android所信任的证书。解决方案之一是去android授权的证书发证机构申请正式证书。
另外一种就是修改客户端代码,强制通过所有证书为信任。这样做会有安全漏洞的问题。
代码在Android 4.0.3的三星手机测试通过。
代码:
HttpDownloader.java
=====================================================
package com.we8log.democert;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.*;
import android.util.Log;
public class HttpDownloader {
private URL url=null;
FileUtils fileUtils=new FileUtils();
public int downfile(String urlStr,String path,String fileName)
{
if(fileUtils.isFileExist(path+fileName))
{return 1;}
else{
try {
InputStream input=null;
input = getInputStream(urlStr);
File resultFile=fileUtils.write2SDFromInput(path, fileName, input);
if(resultFile==null)
{
return -1;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return 0;
}
//由于得到一个InputStream对象是所有文件处理前必须的操作,所以将这个操作封装成了一个方法
public InputStream getInputStream(String urlStr) throws IOException
{
InputStream is=null;
url=new URL(urlStr);
trustAllHosts(); // 开启全部证书信任
HttpURLConnection urlConn=(HttpURLConnection)url.openConnection();
is=urlConn.getInputStream();
return is;
}
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
/**
* Trust every server - dont check for any certificate
*/
private static void trustAllHosts() {
final String TAG = "trustAllHosts";
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
Log.i(TAG, "checkClientTrusted");
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
Log.i(TAG, "checkServerTrusted");
}
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
}
=======================================================================================
package com.we8log.democert;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.Environment;
public class FileUtils {
private String SDPATH="";
public String getSDPATH() {
return SDPATH;
}
public FileUtils() {
//SDPATH =this.getApplicationContext().getFilesDir()+"/";
//得到当前外部存储设备的目录
// /SDCARD
//SDPATH =Environment.getRootDirectory()+"/";
//SDPATH = Environment.getDataDirectory()+"/";
//SDPATH = Environment.getExternalStorageDirectory() + "/";
}
/**
* 在SD卡上创建文件
*
* @throws IOException
*/
public File creatSDFile(String fileName) throws IOException {
File file = new File(SDPATH + fileName);
file.createNewFile();
return file;
}
/**
* 在SD卡上创建目录
*
* @param dirName
*/
public File creatSDDir(String dirName) {
File dir = new File(SDPATH + dirName);
dir.mkdir();
return dir;
}
/**
* 判断SD卡上的文件夹是否存在
*/
public boolean isFileExist(String fileName){
File file = new File(SDPATH + fileName);
return file.exists();
}
/**
* 将一个InputStream里面的数据写入到SD卡中
*/
public File write2SDFromInput(String path,String fileName,InputStream input){
File file = null;
OutputStream output = null;
try{
// creatSDDir(path);
//file = creatSDFile(path + fileName);
file = creatSDFile(fileName);
output = new FileOutputStream(file);
byte buffer [] = new byte[4 * 1024];
while((input.read(buffer)) != -1){
output.write(buffer);
}
output.flush();
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
output.close();
}
catch(Exception e){
e.printStackTrace();
}
}
return file;
}
}
====================================================================
package com.we8log.democert;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
private Button downfile=null;
Context context=this;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downfile=(Button)findViewById(R.id.downfile);
downfile.setOnClickListener(new View.OnClickListener() {
// downfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
HttpDownloader httpDownLoader=new HttpDownloader();
int result=httpDownLoader.downfile("https://test.xianrongwang.com/Lemon/data/upfiles/imagScrollpic/atis/null_scrollpic_new_1446011696.png", "", context.getFilesDir()+"/test.png");
// int result=httpDownLoader.downfile("http://avatar.csdn.net/5/7/2/1_zzp_403184692.jpg", "", context.getFilesDir()+"/test.jpg");
if(result==0)
{
Toast.makeText(MainActivity.this, "下载成功!", Toast.LENGTH_SHORT).show();
}
else if(result==1) {
Toast.makeText(MainActivity.this, "已有文件!", Toast.LENGTH_SHORT).show();
}
else if(result==-1){
Toast.makeText(MainActivity.this, "下载失败!", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
=====================================================================
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button android:id="@+id/downfile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="rtrtrtrtrtrt9"/>
</RelativeLayout>
=============================================================================
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.we8log.democert" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
>
<activity
android:name="com.we8log.democert.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>
===================================================
似乎还有第三种解决办法:
android手机自带导入用户的证书。
但是作者没有实验成功,可能因为实验服务器的证书格式不是安卓手机支持的格式。