Java tutorial
/* * Copyright (C) 2012 Daniel Medina <http://danielme.com> * * This file is part of "Android WebView Demo". * * "Android WebView Demo" is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. * * "Android WebView Demo" is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License version 3 * along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.html/> */ package com.danielme.android.webviewdemo; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.webkit.DownloadListener; import android.webkit.WebChromeClient; import android.webkit.WebIconDatabase; import android.webkit.WebSettings.PluginState; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; import com.vol.androidvmdemo.AndroidUtil; import com.vol.androidvmdemo.R; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.entity.BufferedHttpEntity; import org.apache.http.impl.client.DefaultHttpClient; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.regex.Pattern; import snae.tmcandroid.app.TMPublicClient; import snae.tmcandroid.app.UserQuota; import snae.tmcandroid.traffic.TMManager; public class WebViewDemoActivity extends Activity { public static final String START_PAGE = "http://www.baidu.com"; private static final String TAG = "PROXY"; private static final Pattern urlPattern = Pattern.compile("^(https?|ftp|file)://(.*?)"); TMPublicClient publicClient = new TMPublicClient(); String userid; int tenantid; TMManager tmMgr; Switch freeQuotaSwitch; TextView leftQuotaText; boolean running = false; boolean firstResume = true; private WebView webview; private ProgressBar progressBar; private EditText urlEditText; private List<Link> historyStack; private ArrayAdapter<Link> dialogArrayAdapter; private Button stopButton; private ImageView faviconImageView; /** * call back from UI * * @param view */ public void freeQuotaClick(View view) { Switch s = (Switch) view; if (running) { if (!s.isChecked()) { stopUsingFreeQuota(); } if (s.isChecked()) { startUsingFreeQuota(); } } } void startUsingFreeQuota() { if (tmMgr.getStatus() == TMManager.STATUS_CONNECTED) { Log.w(TAG, "already started session", new Exception()); return; } Log.w(TAG, "prepare to start session"); boolean ret = tmMgr.start(userid, String.valueOf(tenantid)); Log.w(TAG, "start session, result:" + ret); if (!ret) { Toast.makeText(this, "??,?:" + tmMgr.getRejectReasonId(), Toast.LENGTH_LONG).show(); freeQuotaSwitch.setEnabled(false); } else { boolean setProxySuccess = false; try { //tmMgr.setProxyICSPlus(webview); //tmMgr.setKitKatWebViewProxy(WebViewDemoActivity.this); setProxySuccess = tmMgr.setProxy(webview); } catch (Exception e) { Toast.makeText(this, ",:" + e.getClass() + e.getMessage(), Toast.LENGTH_LONG).show(); setProxySuccess = false; Log.e(TAG, "set proxy", e); } if (setProxySuccess) { Toast.makeText(this, "?", Toast.LENGTH_SHORT).show(); } else { freeQuotaSwitch.setChecked(false); freeQuotaSwitch.setEnabled(false); Toast.makeText(this, "?~!??!", Toast.LENGTH_SHORT).show(); } //TODO when user idle more than 3 minutes, session time out!! } } void stopUsingFreeQuota() { if (tmMgr != null //&& tmMgr.getStatus() == TMManager.RSP_REASON_VAL_SUCCESS ) { tmMgr.end(); tmMgr.clearProxy(webview); } Toast.makeText(this, "??,???", Toast.LENGTH_SHORT).show(); } @SuppressLint({ "SetJavaScriptEnabled", "NewApi" }) @Override public void onCreate(Bundle savedInstanceState) { setTitle("?"); AndroidUtil.removeStrict(); super.onCreate(savedInstanceState); setContentView(R.layout.main); historyStack = new LinkedList<Link>(); webview = (WebView) findViewById(R.id.webkit); faviconImageView = (ImageView) findViewById(R.id.favicon); urlEditText = (EditText) findViewById(R.id.url); progressBar = (ProgressBar) findViewById(R.id.progressbar); stopButton = ((Button) findViewById(R.id.stopButton)); //favicon, deprecated since Android 4.3 but it's still necesary O_O ? WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath()); freeQuotaSwitch = (Switch) findViewById(R.id.freeQuotaSwitch); leftQuotaText = (TextView) findViewById(R.id.leftQuota); SharedPreferences settings = getSharedPreferences("setting", 0); userid = settings.getString("userid", "123"); tenantid = Integer.parseInt(settings.getString("tenantid", "3")); // check balance long balance = updateLeftQuota(); freeQuotaSwitch.setChecked(balance > 0); tmMgr = new TMManager(); // javascript and zoom webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setBuiltInZoomControls(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { webview.getSettings().setPluginState(PluginState.ON); } else { //IMPORTANT!! this method is no longer available since Android 4.3 //so the code doesn't compile anymore //webview.getSettings().setPluginsEnabled(true); } // downloads // webview.setDownloadListener(new CustomDownloadListener()); webview.setWebViewClient(new CustomWebViewClient()); webview.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int progress) { progressBar.setProgress(0); FrameLayout progressBarLayout = (FrameLayout) findViewById(R.id.progressBarLayout); progressBarLayout.setVisibility(View.VISIBLE); WebViewDemoActivity.this.setProgress(progress * 1000); TextView progressStatus = (TextView) findViewById(R.id.progressStatus); progressStatus.setText(progress + " %"); progressBar.incrementProgressBy(progress); if (progress == 100) { progressBarLayout.setVisibility(View.GONE); } } @Override public void onReceivedTitle(WebView view, String title) { WebViewDemoActivity.this.setTitle( getString(R.string.app_name) + " - " + WebViewDemoActivity.this.webview.getTitle()); for (Link link : historyStack) { if (link.getUrl().equals(WebViewDemoActivity.this.webview.getUrl())) { link.setTitle(title); } } } @Override public void onReceivedIcon(WebView view, Bitmap icon) { faviconImageView.setImageBitmap(icon); view.getUrl(); boolean b = false; ListIterator<Link> listIterator = historyStack.listIterator(); while (!b && listIterator.hasNext()) { Link link = listIterator.next(); if (link.getUrl().equals(view.getUrl())) { link.setFavicon(icon); b = true; } } } }); //http://stackoverflow.com/questions/2083909/android-webview-refusing-user-input webview.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_UP: if (!v.hasFocus()) { v.requestFocus(); } break; } return false; } }); } long updateLeftQuota() { UserQuota userQuota = publicClient.getQuota(tenantid, userid); long balance = 0; if (userQuota == null || userQuota.getBalance() <= 0) { leftQuotaText.setText("!"); Toast.makeText(WebViewDemoActivity.this, "????!", Toast.LENGTH_SHORT).show(); freeQuotaSwitch.setChecked(false); freeQuotaSwitch.setEnabled(false); } else { balance = userQuota.getBalance(); leftQuotaText.setText("" + ((int) (balance / 1000000)) + "M"); } return balance; } @Override protected void onDestroy() { super.onDestroy(); stopUsingFreeQuota(); webview.loadUrl(""); webview.stopLoading(); webview.destroy(); } @Override public void onPause() { super.onPause(); webview.onPause(); } @Override protected void onResume() { super.onResume(); webview.onResume(); running = true; if (freeQuotaSwitch.isChecked()) { startUsingFreeQuota(); } if (firstResume) { webview.loadUrl(START_PAGE); webview.requestFocus(); } else { firstResume = false; } } @Override protected void onStart() { super.onStart(); } @Override protected void onStop() { super.onStop(); running = true; stopUsingFreeQuota(); } @Override protected Dialog onCreateDialog(int id) { Builder builder = new Builder(this); builder.setTitle(getString(R.string.history)); builder.setPositiveButton(getString(R.string.clear), new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { historyStack.clear(); } }); builder.setNegativeButton(R.string.close, null); dialogArrayAdapter = new ArrayAdapter<Link>(this, R.layout.history, historyStack) { @Override public View getView(int position, View convertView, ViewGroup parent) { //holder pattern LinkHolder holder = null; if (convertView == null) { LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.history, null); holder = new LinkHolder(); holder.setUrl((TextView) convertView.findViewById(R.id.textView1)); holder.setImageView((ImageView) convertView.findViewById(R.id.favicon)); convertView.setTag(holder); } else { holder = (LinkHolder) convertView.getTag(); } Link link = historyStack.get(position); //show title when available if (link.getTitle() != null) { holder.getUrl().setText(link.getTitle()); } else { holder.getUrl().setText(link.getUrl()); } Bitmap favicon = link.getFavicon(); if (favicon == null) { holder.getImageView().setImageDrawable( super.getContext().getResources().getDrawable(R.drawable.favicon_default)); } else { holder.getImageView().setImageBitmap(favicon); } return convertView; } }; builder.setAdapter(dialogArrayAdapter, new OnClickListener() { public void onClick(DialogInterface dialog, int item) { webview.loadUrl(historyStack.get(item).getUrl()); stopButton.setEnabled(true); } }); return builder.create(); } @Override protected void onPrepareDialog(int id, Dialog dialog) { dialogArrayAdapter.notifyDataSetChanged(); super.onPrepareDialog(id, dialog); } // back button // @Override // public void onBackPressed() { // if (webview.canGoBack()) { // webview.goBack(); // } else { // super.onBackPressed(); // } // } public void go(View view) { // hides the keyboard InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(urlEditText.getWindowToken(), 0); if (checkConnectivity()) { stopButton.setEnabled(true); //http protocol by default if (!urlPattern.matcher(urlEditText.getText().toString()).matches()) { urlEditText.setText("http://" + urlEditText.getText().toString()); } webview.loadUrl(urlEditText.getText().toString()); } } public void back(View view) { if (checkConnectivity()) { webview.goBack(); } } public void forward(View view) { if (checkConnectivity()) { webview.goForward(); } } public void stop(View view) { webview.stopLoading(); Toast.makeText(this, getString(R.string.stopping), Toast.LENGTH_LONG).show(); } public void history(View view) { showDialog(0); } private void updateButtons() { Button backButton = (Button) WebViewDemoActivity.this.findViewById(R.id.backButton); if (webview.canGoBack()) { backButton.setEnabled(true); } else { backButton.setEnabled(false); } Button forwardButton = (Button) WebViewDemoActivity.this.findViewById(R.id.forwardButton); if (webview.canGoForward()) { forwardButton.setEnabled(true); } else { forwardButton.setEnabled(false); } updateLeftQuota(); } /** * Checks networking status. */ private boolean checkConnectivity() { boolean enabled = true; ConnectivityManager connectivityManager = (ConnectivityManager) this .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = connectivityManager.getActiveNetworkInfo(); if ((info == null || !info.isConnected() || !info.isAvailable())) { enabled = false; Builder builder = new Builder(this); builder.setIcon(android.R.drawable.ic_dialog_alert); builder.setMessage(getString(R.string.noconnection)); builder.setCancelable(false); builder.setNeutralButton(R.string.ok, null); builder.setTitle(getString(R.string.error)); builder.create().show(); } return enabled; } // DOWNLOAD MANAGER WITH ASYNCTASK class CustomWebViewClient extends WebViewClient { // the current WebView will handle the url @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.endsWith(".mp3") || url.endsWith(".aac")) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse(url), "audio/mpeg"); startActivity(intent); return true; } return false; } /** * public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { * return shouldInterceptRequest(view, request.getUrl().toString()); * } * * @Override public WebResourceResponse shouldInterceptRequest(WebView view, final String url) { * Log.w(TAG, "shouldInterceptRequest:" + url); * <p/> * if (!url.startsWith("http")) { * return super.shouldInterceptRequest(view, url); * } * <p/> * if (!usingFreeQuota) { * return super.shouldInterceptRequest(view, url); * } else { * // using proxy * <p/> * Log.w(TAG, "start using proxy to fetch " + url); * <p/> * try { * TMURL tmUrl = tmMgr.getUrl(url); * HttpURLConnection conn = tmUrl.getHttpUrlConnection(); * int statusCode = conn.getResponseCode(); * if (statusCode == HttpURLConnection.HTTP_OK) { * Log.w(TAG, String.format("status code is %d for getting url:%s", * statusCode, url)); * String mimeType = conn.getContentType(); * String encoding = conn.getContentEncoding(); * <p/> * if (mimeType != null && mimeType.contains(";")) { * String[] split = mimeType.split(";"); * mimeType = split[0]; * try { * encoding = split[1].substring(split[1].indexOf("=") + 1); * } catch (Exception e) { * Log.e(TAG, "", e); * } * } * InputStream is = conn.getInputStream(); * <p/> * WebResourceResponse res = new WebResourceResponse(mimeType, encoding, is); * return res; * <p/> * } else if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED) { * Log.w(TAG, "no more balance."); * <p/> * //WARN USER * WebViewDemoActivity.this.runOnUiThread(new Runnable() { * @Override public void run() { * Toast.makeText(WebViewDemoActivity.this, "????,?!", Toast.LENGTH_LONG).show(); * usingFreeQuota = false; * freeQuotaSwitch.setChecked(false); * stopUsingFreeQuota(); * } * }); * <p/> * } else { * Log.w(TAG, String.format("status code got %d.", statusCode)); * } * } catch (Exception e) { * Log.e(TAG, "", e); * } * <p/> * return super.shouldInterceptRequest(view, url); * } * <p/> * } */ // history and navigation buttons @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { if (checkConnectivity()) { //TEMP //Toast.makeText(WebViewDemoActivity.this,"proxy:" + ProxySelector.getDefault(), Toast.LENGTH_SHORT ).show(); //resets favicon WebViewDemoActivity.this.faviconImageView.setImageDrawable( WebViewDemoActivity.this.getResources().getDrawable(R.drawable.favicon_default)); // shows the current url WebViewDemoActivity.this.urlEditText.setText(url); //only one occurrence boolean b = false; ListIterator<Link> listIterator = historyStack.listIterator(); while (listIterator.hasNext() && !b) { if (listIterator.next().getUrl().equals(url)) { b = true; listIterator.remove(); } } Link link = new Link(url, favicon); historyStack.add(0, link); stopButton.setEnabled(true); updateButtons(); } } @Override public void onPageFinished(WebView view, String url) { stopButton.setEnabled(false); updateButtons(); } // handles unrecoverable errors @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Builder builder = new Builder(WebViewDemoActivity.this); builder.setMessage(description).setPositiveButton((R.string.ok), null).setTitle("onReceivedError"); builder.show(); } } class CustomDownloadListener implements DownloadListener { public void onDownloadStart(final String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { Builder builder = new Builder(WebViewDemoActivity.this); builder.setTitle(getString(R.string.download)); builder.setMessage(getString(R.string.question)); builder.setCancelable(false).setPositiveButton((R.string.ok), new OnClickListener() { public void onClick(DialogInterface dialog, int id) { new DownloadAsyncTask().execute(url); } }).setNegativeButton((R.string.cancel), new OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); builder.create().show(); } } private class DownloadAsyncTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... arg0) { String result = ""; String url = arg0[0]; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); InputStream inputStream = null; FileOutputStream fileOutputStream = null; try { HttpResponse httpResponse = httpClient.execute(httpGet); BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(httpResponse.getEntity()); inputStream = bufferedHttpEntity.getContent(); String fileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/webviewdemo"; File directory = new File(fileName); File file = new File(directory, url.substring(url.lastIndexOf("/"))); directory.mkdirs(); // commons-io, I miss you :( fileOutputStream = new FileOutputStream(file); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while (inputStream.available() > 0 && (len = inputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, len); } fileOutputStream.write(byteArrayOutputStream.toByteArray()); fileOutputStream.flush(); result = getString(R.string.result) + file.getAbsolutePath(); } catch (Exception ex) { Log.e(WebViewDemoActivity.class.toString(), ex.getMessage(), ex); result = ex.getClass().getSimpleName() + " " + ex.getMessage(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException ex) { Log.e(WebViewDemoActivity.class.toString(), ex.getMessage(), ex); result = ex.getClass().getSimpleName() + " " + ex.getMessage(); } } if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException ex) { Log.e(WebViewDemoActivity.class.toString(), ex.getMessage(), ex); result = ex.getClass().getSimpleName() + " " + ex.getMessage(); } } } } else { result = getString(R.string.nosd); } return result; } @Override protected void onPostExecute(String result) { Builder builder = new Builder(WebViewDemoActivity.this); builder.setMessage(result).setPositiveButton((R.string.ok), null) .setTitle(getString(R.string.download)); builder.show(); } } }