android WebView将新浪天气为我所用 ------>仅供娱乐
新浪天气提供了一个网页 http://w.sina.com
浏览器访问:
这效果还可以了哦,直接用webview加载出来,效果也可以了哦,不过,这不是我要的。我不希望在我写的应用里到处铺满sina的logo,我喜欢的效果是这样的:
这样干净利索,多好。
如果你也喜欢,那下面就一起来改造它吧:
首先创建android项目:
先写layout:
activity_weather_sina.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_weatherpage" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <WebView android:id="@+id/wv_oauth" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
不介绍啦,就放了一个WEBVIEW
接下来就写activity了:SinaPage.java
package your.package; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.graphics.Bitmap; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; public class SinaPage extends Activity { private WebView webView; //url之所以写成这样而没有用final直接写死是有原因的。当某个端口被禁用后 貌似是8084, //执行js脚本的时候就会没有效果,所以我最后拿这个URL来做了下判断,看是否禁用了端口(正常情况完全不用考虑的) private static String URL = "http://w.sina.cn"; private ProgressDialog dialog; //在加载的时候,我们最好给显示一个进度对话框,不然页面显得太呆板了 private boolean isshow=false; //用来控制对话框的 private Runnable runCallback; //这是一个回调,详细看下面的注释 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_weather_sina); /*** * 这个是js脚本,下个文件我们再详细介绍 */ final String strScript = "javascript:(function(){var sum=1;var _el = document.getElementsByTagName('div');for (var i=0; i<_el.length; i++ ) {if (_el[i].className=='footer'||_el[i].className=='nav2'||_el[i].className=='bar3'||_el[i].className=='n2'||_el[i].className=='n1'||_el[i].className=='ss') {_el[i].style.display='none';} else if (_el[i].className=='barw') {sum++;}if(sum>2){_el[i].style.display='none'}};var array = document.getElementsByTagName('a');for(var i=0;i<array.length;i++) {var em = array[i];if(em.innerText=='\u67E5\u770B\u672A\u6765\u5929\u6C14\u8BE6\u60C5'||em.innerText=='\u751F\u6D3B\u6307\u6570') {em.style.display='none';}if(em.innerText=='\u56FD\u9645'||em.innerText=='\u65B0\u6D6A\u5929\u6C14') {em.parentElement.style.display='none';}}window.js2java.javascriptFinished()})()"; webView = (WebView) this.findViewById(R.id.wv_oauth); webView.setVisibility(View.INVISIBLE); if (getNetworkIsAvailable(SinaPage.this)) { if(!isFinishing()){ handler.sendEmptyMessage(1); isshow = true; webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(this, "js2java"); webView.setHorizontalScrollBarEnabled(false); webView.setHorizontalScrollbarOverlay(false); webView.setWebViewClient(new WebViewClient() { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { webView.setVisibility(View.INVISIBLE); handler.postDelayed( runCallback = new Runnable() { public void run() { System.out.println("当前加载进度------->"+SinaPage.this.webView.getProgress()); /** * 超时后,首先判断页面加载进度,超时并且进度小于100,就执行超时后的动作 * * 这里是超时的处理 放在一个runnable接口中做的 */ if (SinaPage.this.webView.getProgress() < 100) { Log.d("testTimeout", "timeout..........."); Message msg = new Message(); msg.what = 100; handler.sendMessage(msg); } } }, 15000); } public boolean shouldOverrideUrlLoading(WebView view, String url) { // 重写此方法表明点击网页里面的链接还是在当前的webview里跳转, // 不跳到浏览器那边 // 如果不重写这个方法,那么webView将会打开手机中的浏览器 webView.setVisibility(View.INVISIBLE); if(getNetworkIsAvailable(SinaPage.this)) view.loadUrl(url); else{ //网络不可用的时候发送异常 Toast.makeText(getApplicationContext(), "网络错误", 0).show(); handler.sendEmptyMessage(101); } if(!isshow){ handler.sendEmptyMessage(1); isshow = true; } return true; } @Override public void onPageFinished(WebView view, String url) { webView.setVisibility(View.INVISIBLE); try{ // //网页加载完成后,加载js脚本 System.out.println("-------->url = "+url); URL = url;//这里涉及新浪他们服务器重定向,如果某些端口禁用了,那么重定向的url就不会生效 //这里是执行我们上面的js脚本 最最重要的一步 view.loadUrl(strScript); }catch(Throwable t){ //这里是加载脚本可能出现的异常,我们暂时不作处理 } } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Toast.makeText(getApplicationContext(), "网络错误", 0).show(); } }); webView.loadUrl(URL); } }else{ Toast.makeText(getApplicationContext(), "网络不可用,请打开网络后重试", 0).show(); } } Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case 0: /*** * 修改在 8084端口被禁用的情况下,获取城市失败后重定向的问题 * * 处理方法:手动添加重定向(直接搜索上海的天气情况) */ if(URL.equals("http://w.sina.cn/")){ //重定向失败了 URL没有被赋值,我们就去加载上海的天气,上海天气的url为下面的这个url //http://weather1.sina.cn/dpool/weather_new/forecast_new.php?city=%E4%B8%8A%E6%B5%B7&vt=4 webView.loadUrl("http://weather1.sina.cn/dpool/weather_new/forecast_new.php?city=%E4%B8%8A%E6%B5%B7&vt=4"); System.out.println("手动重定向"); }else{ //添加标识 System.out.println("显示页面"); webView.setVisibility(View.VISIBLE); if(dialog!=null && dialog.isShowing()&&!SinaPage.this.isFinishing()){ dialog.dismiss(); isshow = false; } } break; case 1: /*** * 收到这个消息,就显示对话框 */ if(!SinaPage.this.isFinishing()&&getNetworkIsAvailable(SinaPage.this)){ dialog = ProgressDialog.show(SinaPage.this, null, "正在为您加载...", true); dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(true); dialog.setOnCancelListener(new OnCancelListener() { public void onCancel(DialogInterface dialog) { if(webView.canGoBack()){ webView.goBack(); } } }); } break; case 100: /*** * 收到这个消息,就提示网络不好 多数情况是超时了 ,超时 在runable里面处理的 */ Toast.makeText(getApplicationContext(), "网络状态不佳", 0).show(); webView.setVisibility(View.INVISIBLE); webView.stopLoading(); if(dialog!=null && dialog.isShowing()){ dialog.dismiss(); isshow = false; } break; case 101: if(dialog!=null && dialog.isShowing()&&!SinaPage.this.isFinishing()){ dialog.dismiss(); isshow = false; webView.stopLoading(); } break; default: break; } }; }; public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if(dialog!=null && dialog.isShowing()){ dialog.dismiss(); return true; } if(webView.canGoBack()){ webView.goBack(); return false; } } return super.onKeyDown(keyCode, event); } /*** * 这个方法是提供给js脚本去回调的, * js脚本执行完,就会调这个方法,通知界面显示webview控件 */ public void javascriptFinished() { handler.sendEmptyMessage(0); handler.removeCallbacks(runCallback); } @Override protected void onDestroy() { //退出的时候要注意我们的对话框可能会引起程序挂掉,需要处理哦 if(dialog!=null && dialog.isShowing()){ dialog.dismiss(); isshow = false; handler.removeCallbacks(runCallback); } super.onDestroy(); } /** * 检查网络是否可用 * @return true 为网络可用 */ public boolean getNetworkIsAvailable(Context context) { ConnectivityManager manager = (ConnectivityManager) context .getSystemService(context.CONNECTIVITY_SERVICE); NetworkInfo info = manager.getActiveNetworkInfo(); if (info == null || !info.isConnected()) { return false; } if (info.isRoaming()) { return true; } return true; } }
为了节省空间,我把该写的都作为注释写上去了哦,到这就大功告成了?还没有哦,清单文件的权限一定要记得配置:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.package" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".SinaPage" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
到这就大功告成了哦
赶紧试一下吧
最后补充一个javascript脚本相关内容
我们使用到的js脚本
javascript:(function(){var sum=1;var _el = document.getElementsByTagName('div');for (var i=0; i<_el.length; i++ ) {if (_el[i].className=='footer'||_el[i].className=='nav2'||_el[i].className=='bar3'||_el[i].className=='n2'||_el[i].className=='n1'||_el[i].className=='ss') {_el[i].style.display='none';} else if (_el[i].className=='barw') {sum++;}if(sum>2){_el[i].style.display='none'}};var array = document.getElementsByTagName('a');for(var i=0;i<array.length;i++) {var em = array[i];if(em.innerText=='\u67E5\u770B\u672A\u6765\u5929\u6C14\u8BE6\u60C5'||em.innerText=='\u751F\u6D3B\u6307\u6570') {em.style.display='none';}if(em.innerText=='\u56FD\u9645'||em.innerText=='\u65B0\u6D6A\u5929\u6C14') {em.parentElement.style.display='none';}}window.js2java.javascriptFinished()})()
就是用来隐藏那些个不需要的节点的,js我就不出来献丑了