您的位置:首页 > 理论基础 > 计算机网络

Android WebView with https loadUrl shows blank/empty page

2012-10-10 08:19 651 查看


AndroidWebViewwithhttpsloadUrlshowsblank/emptypage


September28,2010

IrecentlyencounteredthisproblemwhiletryingtodevelopaWebViewthatissupportedonDoughnut(1.6)andabove.WhenpresentedwithahttpsurltheWebViewjustrendersablankpage.

ItseemsthatuntilFroyo,Androiddidn’tprovideapublicAPItoletyoumanuallydecideifyouwantedtoproceedtoanuntrustedwebsiteviaaWebView.

Notethatinthiscaseitisnoteventhatthewebsitewasuntrusted(intheconventionalsense)–itisbecauseThawteisnotinthedefaultlistoftrustedcertificateauthoritiesonAndroid.IfyouusethestandardwebbrowseronAndroid,thebrowser
presentsatypicalwarningdialog(aspresentedbelow)thatenablesyoutoacceptthecertificateandcarryon.





IfyouareusingFroyoasthetargetSDKthenyoucanuse:

1
engine
=(WebView)findViewById(R.id.my_webview);
2
engine.setWebViewClient(
new
WebViewClient()
{
3
public
void
onReceivedSslError
(WebViewview,SslErrorHandlerhandler,SslErrorerror){
4
handler.proceed()
;
5
}
6
}
However,ifyouarenotusingFroyothenitseemsyouareoutofluck.Aftersomeresearch,IconcludedthatIhadthefollowingoptions:

a)interceptallpagerequestsandforwardtoexternalwebbrowserifurlbeginswithhttps(notacleanorniceuserexperienceandtotallyunnecessaryforFroyoandabove)

b)addcertificateofwebsitetolocalkeystore(inthiscaseIamservingmultiplewebpagesandtheoriginofmanyoftheseisnotknownuntilruntime)

c)makeFroyotheminSDKanddiscardpreviousversionsofAndroid(notasuitableoption)

d)hackandusesomeprivateapis(theoptiondescribedbelow)

Tosolvethisproblemwehavetouseaprivateinterface(notpublishedonSDKbutpresentinrealSDKruntime).AsyoucanseeintheAndroidsrctree,theonReceivedSslErroris
indeedpresent(andused–itsimplycancelstherequest)inDoughnut.However,thismethodisnotpresentedtousintheSDK-itishiddenbecauseitcontainsaparametertypeSslErrorwhichislocatedinahiddenpackage.Therefore,weneedtocopythese
srcfilesintoourprojectsothatwecanaccessthem:

1)CopyWebViewClient.javaintothepackage“android.webkit”
withinyoursrcfolder.

2)CopySslError.javaintothepackage“android.net.http”
withinyoursrcfolder.





3)SincewereplicatedthepathstothesrcfilesintheSDK,ourcodetooverrideonSslErrorabovenowworksonAndroid1.6.

Caution:bearinmindthatweareusingaprivateAPIandGooglereservetherighttochangeprivateAPIsatanytime–thoughinthiscaseitisunlikelysincethey’venowmadethisavailableinFroyo.


Sharethis:

Share


Likethis:

Like

Onebloggerlikesthis.





Postedbydamianflannery

FiledinAndroid,Java

Tags:Android,https,private
api,ssl,webview

20
Comments»


20Responsesto“AndroidWebViewwithhttpsloadUrlshowsblank/emptypage”


BanoSays:

September29,2010at9:34
am
Hi,Ihaveusedthismethodandothermethod(likethishttp://wongcr.blogspot.com/2009/03/disabling-certificate-validation-in.html)
andIcan’tseeahttpspageintheWebView.Canyouhelpme?

Reply


damianflannerySays:

September29,2010at9:42
am
Icantry.Yourrequestforhelpisabitvaguethough…

Reply


BanoSays:

September29,2010at10:26
pm
Sorry,Idid’tknowifIshouldwritealargepost.MyproblemiswiththeHttpPostconnections,Icreatean“DefaultHttpClient”anda“HttpPost”,nextIcreatealistofvaluestosendandfinallyexecuteit.

Thisworkinhttpconections,butinhttpsconectionsItrythemethodsIfindonInternetanddon’tgetittowork(Getnottrustedcertificate).

Thelastcode(withcustomSSLShocketFactoryandTrustManager):

try{

////

SchemeRegistryschemeRegistry=newSchemeRegistry();

schemeRegistry.register(newScheme(“https”,newEasySSLSocketFactory(),443));

HttpParamsparams=newBasicHttpParams();

SingleClientConnManagermgr=newSingleClientConnManager(params,schemeRegistry);

DefaultHttpClienthc=newDefaultHttpClient(mgr,params);

///

//DefaultHttpClienthc=newDefaultHttpClient();

ResponseHandlerres=newBasicResponseHandler();

HttpPostpostMethod=newHttpPost(DIRECCION);

ListnameValuePairs=newArrayList(3);

nameValuePairs.add(newBasicNameValuePair(“usuario”,nom));

nameValuePairs.add(newBasicNameValuePair(“tipo_firma”,tip));

nameValuePairs.add(newBasicNameValuePair(“string_img”,img));

postMethod.setEntity(newUrlEncodedFormEntity(nameValuePairs));

Stringresponse=hc.execute(postMethod,res);

returnresponse;

}catch(ClientProtocolExceptione){

pasos=“Excepción:”+e.toString();

}catch(IOExceptione){

//“Error1:Unabletoestablishcommunicationwiththeserver.Checkyourconfiguration.”

pasos=pasos+“Excepción:”+e.toString();

}

ifyoucanhelpme,itwouldveryhelpfull.

PD:Sorryformybadenglish…

Reply


damianflannerySays:

September30,2010at7:33
am
Thebestwaywouldbetoaddtheserver’spubliccertificatetoyourAndroidApp’strustedstore:

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

Otherwiseyoucouldsimplystopcheckingallhostsfortheircertificate:

http://stackoverflow.com/questions/995514/https-connection-android/1000205#1000205

Reply


BanoSays:

September30,2010at9:39
am
Finally,yourpostgivemeanidea.IchangetheDefaultHttpClientforHttpsURLConection,usingOutputStreamandInputStreamtothecomunication.NextIapplythesecondlinkyougiveme(Ivisitedityetbutdidn’thelpmeinmypreviouslyidea).

Ican’tusetheSSLcertificatecreatorbecauseIhaven’tdirectaccesstotheserveroftheproyect.

thecodeofSend:

try{

////

Stringlocation=“usuario=”+nom+“&tipo_firma=”+tip+“&string_img=”+img;

URLurl=newURL(DIRECCION);

trustAllHosts();

HttpsURLConnectionhttps=(HttpsURLConnection)url.openConnection();

https.setHostnameVerifier(DO_NOT_VERIFY);

https.setRequestMethod(“POST”);

https.setDoOutput(true);

https.setUseCaches(false);

https.setRequestProperty(“Content-Type”,

“application/x-www-form-urlencoded”);

https.connect();

OutputStreamost=https.getOutputStream();

DataOutputStreamout=newDataOutputStream(ost);

out.writeBytes(location);

out.flush();

ost=null;

InputStreamist=https.getInputStream();

BufferedReaderin=newBufferedReader(newInputStreamReader(ist));

StringBuffersb=newStringBuffer();

char[]c=newchar[1];

while(in.read(c,0,1)==1){

sb.append(c[0]);

}

Stringresponse=sb.toString();

///

returnresponse;

}catch(ClientProtocolExceptione){

pasos=“Excepción:”+e.toString();

}catch(IOExceptione){

//“Error1:Unabletoestablishcommunicationwiththeserver.Checkyourconfiguration.”

pasos=pasos+“Excepción:”+e.toString();

}

Nextaddingthetrustpart:

//alwaysverifythehost–dontcheckforcertificate

finalstaticHostnameVerifierDO_NOT_VERIFY=newHostnameVerifier(){

publicbooleanverify(Stringhostname,SSLSessionsession){

returntrue;

}

};

/**

*Trusteveryserver–dontcheckforanycertificate

*/

privatestaticvoidtrustAllHosts(){

//Createatrustmanagerthatdoesnotvalidatecertificatechains

TrustManager[]trustAllCerts=newTrustManager[]{newX509TrustManager(){

publicjava.security.cert.X509Certificate[]getAcceptedIssuers(){

returnnewjava.security.cert.X509Certificate[]{};

}

publicvoidcheckClientTrusted(X509Certificate[]chain,StringauthType)throwsCertificateException{}

publicvoidcheckServerTrusted(X509Certificate[]chain,StringauthType)throwsCertificateException{}

}};

//Installtheall-trustingtrustmanager

try{

SSLContextsc=SSLContext.getInstance(“TLS”);

sc.init(null,trustAllCerts,newjava.security.SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

}catch(Exceptione){

e.printStackTrace();

}

}

Thanksforyourhelp.

Reply


damianflannerySays:

October4,2010at11:25am
You’rewelcome



Vito
AndoliniSays:

January12,2012at9:41
pm
CrazyBob’sarticleisasolutionforSSLissueswiththeHttpClient,notwithaWebView.Idon’tbelieveyoucanaddacertificatetotheapp’strustedstoreandhavethatusedbyaWebView.

Reply


WilliamSays:

October12,2010at3:31am
Hi,

Justwantedtothankyoutohaveresolvedmyproblemin2seconds.

Workingoneclair2.1atthemomentIhadexactlythesameissueyoudescribed.Yourfixedavoidedmealotoftroubles.

thanks

William

Reply


AnsariSays:

December27,2010at4:55
am
Thanksalot,theabovesolutionworks.

Reply


Sebastian
BSays:

February23,2011at2:38
pm
Thankyouverymuch,thisisexcellent!!!

IhadbeenstrugglingwiththisforsomehoursbeforeIfoundyoursolution.

Reply


Artem
RussakovskiiSays:

June28,2011at10:31pm
Thanks,washavingthesameprobleminaprojecttargetingAndroid1.6.NowIknowwhattheheckisgoingon.

Reply

Tracks2MilesFacebooklogon«Ben'sPlaceSays:

July1,2011at9:53pm
[...]WebViewjustswallowedthiswithnoerrormessages,butabitofgooglingandfoundthefollowingblogpostabouthowtoworkroundthecertificatemissmatchandevenhowtomakeitworkwithAndroid[...]

Reply


skshelkehelkeSays:

July14,2011at2:05pm
HiAll,

IamtryingtoretrievePOSTparameterfromResponse.butnotablegetitfromandroidWebview.

CouldanyonehelpmeorgiveanideatoretrievePOSTdatafromresponseURL.

Thanks&Regards

Reply


damianflannerySays:

July14,2011at7:05pm
Idon’tthinkwebviewisveryconduciveforthatkindofthingbutthelinkbelowmighthelp.

http://stackoverflow.com/questions/3134389/access-the-http-response-headers-in-a-webview

Reply


RichardSays:

August15,2011at9:57am
IhaveappliedyourtrickanditworksfineuntilIrunonarealAndroiddevice1.6or2.1.ThentheoverloadingofclassesisstopbytheDEXloader!!!anytrickstogetaround?

Reply


RichardSays:

August15,2011at10:05
am
08-1512:03:41.938:DEBUG/dalvikvm(3003):DexOpt:‘Landroid/net/http/SslError;’hasanearlierdefinition;blockingout

08-1512:03:41.938:DEBUG/dalvikvm(3003):DexOpt:‘Landroid/webkit/WebViewClient;’hasanearlierdefinition;blockingout

08-1512:03:41.973:DEBUG/dalvikvm(3003):DexOpt:notverifying‘Landroid/net/http/SslError;’:multipledefinitions

08-1512:03:41.973:DEBUG/dalvikvm(3003):DexOpt:notverifying‘Landroid/webkit/WebViewClient;’:multipledefinitions

08-1512:03:42.153:INFO/dalvikvm(3003):DexOpt:notresolvingambiguousclass‘Landroid/webkit/WebViewClient;’

Reply


tomozeronSays:

August26,2011at9:10pm
HiDamian,

I’vebeenstrugglingacoupleofnightsgettingpostUrltoworkwhenpostingtoahttpssite.ItriedtouseallsortsofTrustedManagersetcetcbutwithnoluck.

ThenIfoundthisgemofyours,readitandinlessthan10minutesIwasup’nrunning.

Ibowmyheadinhumblesubmission.

Thankyou.

/brian

Reply


rpcheSays:

January11,2012at12:28
am
Hello,Damianthnxforthetutorialbutistilldontmanagetogetitwork.maybifuhavesometimeucanhelpmeloadhttpsinmywebview


packagehere.testing.a.cool.app;

importandroid.app.Activity;

importandroid.os.Bundle;

importandroid.view.Window;

importandroid.webkit.WebChromeClient;

importandroid.webkit.WebView;

importandroid.webkit.WebViewClient;

publicclassWebPageLoaderextendsActivity

{

finalActivityactivity=this;

@Override

publicvoidonCreate(BundlesavedInstanceState)

{

super.onCreate(savedInstanceState);

this.getWindow().requestFeature(Window.FEATURE_PROGRESS);

setContentView(R.layout.main);

WebViewwebView=(WebView)findViewById(R.id.webview);

webView.getSettings().setJavaScriptEnabled(true);

webView.setWebChromeClient(newWebChromeClient(){

publicvoidonProgressChanged(WebViewview,intprogress)

{

activity.setTitle(“Grabbingthebitsandthebytes..”);

activity.setProgress(progress*100);

if(progress==100)

activity.setTitle(R.string.app_name);

}

});

webView.setWebViewClient(newWebViewClient(){

@Override

publicvoidonReceivedError(WebViewview,interrorCode,Stringdescription,StringfailingUrl)

{

//Handletheerror

}

@Override

publicbooleanshouldOverrideUrlLoading(WebViewview,Stringurl)

{

view.loadUrl(url);

returntrue;

}

});

webView.loadUrl(“https://website.willnot.open”);

}

}

Reply


ArthurSays:

January17,2012at1:40
pm
Thanksalot!!!!

Reply


becomingthebeastSays:

April18,2012at5:31pm
GreatpostDamian.

Asalwaysyourarticlesaremostuseful.

Thankyou!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: