安卓开发新人,刚着手项目中用html实现应用的某些模块,在编写带webview的Activity时就遇到的问题不断尝试,并改进自己的webviewActivity,最后给出自己的源码,刚接触webview的童鞋可以参考其中的解决方案。
其中涉及到的问题有:
webview加载页面的基本配置
使webview显示网页加载进度
webview的后退、前进、刷新、关闭的实现
Android通过webview的cookie来传键值对给html端
使webview支持文件的上传
webview中如何给JS提供接口,让JS能调用Android的方法
将JS的Alert转换为Android的AlertDialog
调用该activity来加载页面,只需要用以下片断即可
intent.setClass(MainActivity_3.this, WebViewActivity.class); intent.putExtra("url", "file:///android_asset/index.html");// FIXME
intent.putExtra("title", "测试");
startActivity(intent);
public class WebViewActivity extends Activity {
private final static int FINISH_ACTIVITY = 0;
private final static int REQUEST_UPLOAD_FILE_CODE = 2;
private ValueCallback mUploadFile;
private final String TAG = "WebViewActivity ";
private WebView webview;
private String url;
private Handler handler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.activity_webview);
webview = (WebView) findViewById(R.id.webView);
url = getIntent().getStringExtra("url");
getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
Window.PROGRESS_VISIBILITY_ON);
//给页面的actionBar加上回退按钮
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setBackgroundDrawable(
getResources().getDrawable(R.color.deepgrey));
//设置webview的settings和client
configWebview();
setCookie();
// 加载 页面
loadURL();
}
//给html页面传递的用户数据都放在cookie中
private void setCookie() {
SharedPreferences userInfoSP = MyApplication.getInstance()
.getUserinfoSharedPreferences();
CookieSyncManager cookieSyncManager = CookieSyncManager
.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
String domain = "app.issll.com";
Cookie cname = null;
try {//若不用URLEncoder编码,中文在某些机型上会出现乱码
cname = new Cookie(domain, "userName", URLEncoder.encode(
userInfoSP.getString("name", ""), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Cookie cplotid = new Cookie(domain, "plotId",
UserSelectedAddress.plotid);
Cookie cLongtitude = new Cookie(domain, "longtitude",
String.valueOf(UserSelectedAddress.myLongitude));
Cookie cLatitude = new Cookie(domain, "latitude",
String.valueOf(UserSelectedAddress.myLatitude));
Cookie cUserId = new Cookie(domain, "userId", userInfoSP.getString(
"userid", ""));
MyDebugUtils.d(TAG, cplotid.toString());
MyDebugUtils.d(TAG, cUserId.toString());
MyDebugUtils.d(TAG, cname.toString());
cookieManager.removeAllCookie();
cookieManager.setCookie(url, "" + cUserId);
cookieManager.setCookie(url, "" + cname);
cookieManager.setCookie(url, "" + cplotid);
cookieManager.setCookie(url, "" + cLongtitude);
cookieManager.setCookie(url, "" + cLatitude);
cookieSyncManager.startSync();
}
private void setActionbarTitle() {
String title = getIntent().getStringExtra("title");
if (title != null)
getActionBar().setTitle(title);
else
getActionBar().setTitle(R.string.app_name);
}
private void loadURL() {
try {
webview.loadUrl(url);
} catch (Exception e) {
MyDebugUtils.e(TAG + url, e.getLocalizedMessage());
}
}
//友盟SDK的方法
@Override
protected void onResume() {
MobclickAgent.onResume(this);
super.onResume();
}
@Override
protected void onPause() {
MobclickAgent.onPause(this);
super.onPause();
}
@Override
protected void onDestroy() {
webview.destroy();
super.onDestroy();
}
@SuppressWarnings("deprecation")
private void configWebview() {
// 允许javascript代码执行
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
settings.setAppCacheMaxSize(8 * 1024 * 1024);
settings.setRenderPriority(RenderPriority.HIGH);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setAppCacheEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setAllowFileAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setDefaultTextEncodingName("utf-8");
// 在当前页面打开链接,而不是启动用户手机上安装的浏览器打开
webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
webview.loadUrl(url);
return true;
}
});
webview.setWebChromeClient(new WebChromeClient() {
// 使webview可以更新进度条
@Override
public void onProgressChanged(WebView view, int newProgress) {
WebViewActivity.this.setTitle("加载中……");
WebViewActivity.this.setProgress(newProgress * 100);
if (newProgress == 100)
setActionbarTitle();
}
//使JS alert可以以Android的AlertDiaolog形式弹出
@Override
public boolean onJsAlert(WebView view, String url, String message,
final JsResult result) {
AlertDialog.Builder builder = new Builder(WebViewActivity.this)
.setMessage(message).setPositiveButton("确定",
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
result.confirm();
}
});
builder.setCancelable(true);
builder.show();
return true;
}
//html中上传点击input type为file的控件时会调用下列方法,在Android4.4中无效,待修复
// Android 4.1+
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback uploadFile,
String acceptType, String capture) {
openFileChooser(uploadFile);
}
// Android 3.0 +
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback uploadFile,
String acceptType) {
openFileChooser(uploadFile);
}
// Android 3.0
public void openFileChooser(ValueCallback uploadFile) {
mUploadFile = uploadFile;
startActivityForResult(createCameraIntent(),
REQUEST_UPLOAD_FILE_CODE);
}
});
// 在js中用window.injs.方法名来调用InJavaScript类中的方法
webview.addJavascriptInterface(new InJavaScript(), "android");
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
private Intent createCameraIntent() {
Intent imageIntent = new Intent(Intent.ACTION_GET_CONTENT);// 选择图片文件
imageIntent.setType("image/*");
return imageIntent;
}
// 使后退键可以达到网页回退功能,而不是关闭activity
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) {
webview.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
//添加菜单栏的几个功能键
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.webview, menu);
return super.onCreateOptionsMenu(menu);
}
/**
* 给javascript调用的代码
*
*/
private final class InJavaScript {
//可以用JS关闭本Activity
@android.webkit.JavascriptInterface
public void finish() {
handler.sendEmptyMessage(FINISH_ACTIVITY);
}
//可以用JS触发一个分享文本信息的intent
@android.webkit.JavascriptInterface
public void sharelink(String link){
Intent i=new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_SUBJECT, "分享");
i.putExtra(Intent.EXTRA_TEXT, "share this:"+link);
startActivity(Intent.createChooser(i, "请选择分享方式"));
}
}
/*
* (non-Javadoc)左上角回退可以结束本activity,另有前进、后退、刷新
*
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home://关闭页面
finish();
break;
case R.id.menu_webview_refresh://刷新
webview.reload();
break;
case R.id.menu_webview_back://后退
if (webview.canGoBack())
webview.goBack();
break;
case R.id.menu_webview_forward://前进
if (webview.canGoForward())
webview.goForward();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//选择文件后回调给JS一个URI
if (requestCode == REQUEST_UPLOAD_FILE_CODE && resultCode == RESULT_OK) {
if (null == mUploadFile)
return;
Uri result = (null == data) ? null : data.getData();//注,此处data.getData(),若为data则仅是contentProvider的地址将不能为JS识别
if (null != result) {
mUploadFile.onReceiveValue(result);
mUploadFile = null;
}
//如果用户取消了选择文件操作,必须回调一个null的URI给JS,否则webview将会死掉
} else if (requestCode == REQUEST_UPLOAD_FILE_CODE &&resultCode == RESULT_CANCELED) {
Uri result = null;
mUploadFile.onReceiveValue(result);
mUploadFile = null;
}
}
//用来处理UI操作的handler,可扩展,暂无太大用处……
private static class MyHandler extends Handler {
WeakReference weakReference;
public MyHandler(WebViewActivity webViewActivity) {
weakReference = new WeakReference(webViewActivity);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case FINISH_ACTIVITY:
weakReference.get().finish();
break;
default:
break;
}
super.handleMessage(msg);
}
}
}