package com.ywwxhz.processers; import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Color; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; import android.webkit.JavascriptInterface; import android.webkit.MimeTypeMap; import android.webkit.WebChromeClient; import android.webkit.WebResourceResponse; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; import com.loopj.android.http.JsonHttpResponseHandler; import com.melnykov.fab.FloatingActionButton; import com.nostra13.universalimageloader.core.ImageLoader; import com.ywwxhz.MyApplication; import com.ywwxhz.activitys.ImageViewActivity; import com.ywwxhz.activitys.NewsDetailActivity; import com.ywwxhz.cnbetareader.R; import com.ywwxhz.data.DataProviderCallback; import com.ywwxhz.data.impl.NewsDetailProvider; import com.ywwxhz.entitys.NewsItem; import com.ywwxhz.fragments.NewsDetailFragment; import com.ywwxhz.lib.Configure; import com.ywwxhz.lib.CroutonStyle; import com.ywwxhz.lib.ThemeManger; import com.ywwxhz.lib.database.exception.DbException; import com.ywwxhz.lib.kits.FileCacheKit; import com.ywwxhz.lib.kits.NetKit; import com.ywwxhz.lib.kits.PrefKit; import com.ywwxhz.lib.kits.Toolkit; import com.ywwxhz.widget.AVLoadingIndicatorView.AVLoadingIndicatorView; import org.adw.library.widgets.discreteseekbar.DiscreteSeekBar; import org.apache.http.Header; import org.json.JSONObject; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Locale; import java.util.regex.Matcher; import de.keyboardsurfer.android.widget.crouton.Style; /** * cnBetaReader * Created by 远望の无限(ywwxhz) on 2014/11/1 17:48. */ public class NewsDetailProcesser extends BaseProcesserImpl<String, NewsDetailProvider> implements DataProviderCallback<String> { private View loadFail; private WebView mWebView; private boolean hascontent; private NewsItem mNewsItem; private AVLoadingIndicatorView mProgressBar; private FloatingActionButton mActionButtom; private VideoWebChromeClient client = new VideoWebChromeClient(); private boolean showImage; private boolean convertFlashToHtml5; private boolean fromDB = false; private NewsDetailFragment.NewsDetailCallBack callBack; private String webTemplate = "<!DOCTYPE html><html><head><title></title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\"/>" + "<link rel=\"stylesheet\" href=\"file:///android_asset/style.css\" type=\"text/css\"/><style>.title{color: #%s;}%s</style>" + "<script>var config = {\"enableImage\":%s,\"enableFlashToHtml5\":%s};</script>" + "<script src=\"file:///android_asset/BaseTool.js\"></script>" + "<script src=\"file:///android_asset/ImageTool.js\"></script>" + "<script src=\"file:///android_asset/VideoTool.js\"></script></head>" + "<body><div><div class=\"title\">%s</div><div class=\"from\">%s<span style=\"float: right\">%s</span></div><div id=\"introduce\">%s<div class=\"clear\"></div></div><div id=\"content\">%s</div><div class=\"clear foot\">-- The End --</div></div>" + "<script src=\"file:///android_asset/loder.js\"></script></body></html>"; private String night = "body{color:#9bafcb}#introduce{background-color:#262f3d;color:#616d80}.content blockquote{background-color:#262f3d;color:#616d80}"; private String light = "#introduce{background-color:#F1F1F1;color: #444;}"; private Handler myHandler; private WebSettings settings; private boolean shouldLoadCache; private void hideProgressBar(){ mProgressBar.setVisibility(View.GONE); } public NewsDetailProcesser(NewsDetailProvider provider) { super(provider); } @Override public void onResume() { mWebView.onResume(); } @Override public void onPause() { mWebView.onPause(); } @Override public void onDestroy() { mWebView.stopLoading(); mWebView.destroy(); } @Override public void assumeView(View view) { this.hascontent = false; this.myHandler = new Handler(); initView(view); showImage = PrefKit.getBoolean(mActivity, R.string.pref_show_detail_image_key, true); convertFlashToHtml5 = PrefKit.getBoolean(mActivity, R.string.pref_flash_to_html5_key, true); } @SuppressLint({"AddJavascriptInterface", "SetJavaScriptEnabled"}) private void initView(View view) { this.loadFail = view.findViewById(R.id.message); this.mWebView = (WebView) view.findViewById(R.id.webview); if (ThemeManger.isNightTheme(getActivity())) { this.mWebView.setBackgroundColor(windowBackground); } this.mProgressBar = (AVLoadingIndicatorView) view.findViewById(R.id.loading); this.mActionButtom = (FloatingActionButton) view.findViewById(R.id.action); this.mActionButtom.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { commentAction(); } }); mActionButtom.setScaleX(0); mActionButtom.setScaleY(0); settings = mWebView.getSettings(); settings.setSupportZoom(false); settings.setAllowFileAccess(true); settings.setPluginState(WebSettings.PluginState.ON_DEMAND); settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); settings.setLoadsImagesAutomatically(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WebView.setWebContentsDebuggingEnabled(true); } if (!PrefKit.getBoolean(mActivity, mActivity.getString(R.string.pref_hardware_accelerated_key), true)) { mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } if (NetKit.isWifiConnected()) { settings.setCacheMode(WebSettings.LOAD_DEFAULT); } else { settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); } settings.setTextZoom(PrefKit.getInt(mActivity, "font_size", 100)); mWebView.addJavascriptInterface(new JavaScriptInterface(mActivity), "Interface"); mWebView.setWebChromeClient(client); mWebView.setWebViewClient(new MyWebViewClient()); this.loadFail.setClickable(true); this.loadFail.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { makeRequest(); } }); } public void setNewsItem(int sid, String title) { try { mNewsItem = MyApplication.getInstance().getDbUtils().findById(NewsItem.class, sid); if (mNewsItem == null) { fromDB = false; this.mNewsItem = new NewsItem(sid, title); } else { if(title.length()>0) { mNewsItem.setTitle(title); } fromDB = true; } } catch (DbException e) { fromDB = false; this.mNewsItem = new NewsItem(sid, title); } } @Override public void loadData(boolean startup) { String title = mNewsItem.getTitle(); shouldLoadCache = !title.contains("直播") || title.contains("已完结"); NewsItem mNews = mNewsItem.getSN() == null ? FileCacheKit.getInstance().getAsObject(mNewsItem.getSid() + "", NewsItem.class) : mNewsItem; if (mNews == null || !shouldLoadCache) { makeRequest(); } else { hascontent = true; if(title.length()>0) { mNews.setTitle(title); } mNewsItem = mNews; bindData(); } } public void makeRequest() { provider.loadNewsAsync(mNewsItem.getSid() + ""); } @Override public void onLoadStart() { mProgressBar.setVisibility(View.VISIBLE); mWebView.setVisibility(View.GONE); loadFail.setVisibility(View.GONE); } @Override public void onLoadSuccess(String resp) { if (Configure.STANDRA_PATTERN.matcher(resp).find()) { new AsyncTask<String, String, Boolean>() { @Override protected Boolean doInBackground(String... strings) { hascontent = NewsDetailProvider.handleResponceString(mNewsItem, strings[0], shouldLoadCache); return hascontent; } @Override protected void onPostExecute(Boolean hascontent) { if (hascontent) { bindData(); } else { onLoadFailure(); } } }.execute(resp); } else { onLoadFailure(); } } @Override public void onLoadFinish(int size) { } @Override public void onLoadFailure() { if (!hascontent) { loadFail.setVisibility(View.VISIBLE); if (callBack != null) { callBack.onNewsLoadFinish(mNewsItem, false); } } else { bindData(); mWebView.setVisibility(View.VISIBLE); } hideProgressBar(); Toolkit.showCrouton(mActivity, R.string.message_no_network, Style.ALERT); } private void bindData() { String colorString = Integer.toHexString(titleColor); String add; if (ThemeManger.isNightTheme(getActivity())) { add = night; } else { add = light; } mActivity.setTitle(mNewsItem.getTitle()); String data = String.format(Locale.CHINA, webTemplate, colorString.substring(2, colorString.length()), add, showImage, convertFlashToHtml5, mNewsItem.getTitle(), mNewsItem.getFrom(), mNewsItem.getInputtime(), mNewsItem.getHometext(), mNewsItem.getContent()); mWebView.loadDataWithBaseURL(Configure.BASE_URL, data, "text/html", "utf-8", null); mActionButtom.postDelayed(new Runnable() { @Override public void run() { if (callBack != null) { callBack.onNewsLoadFinish(mNewsItem, true); } if (fromDB) { try { MyApplication.getInstance().getDbUtils().saveOrUpdate(mNewsItem); } catch (DbException ignored) { } } mActionButtom.setVisibility(View.VISIBLE); mActionButtom.animate().scaleX(1).scaleY(1).setDuration(500).setInterpolator(new AccelerateDecelerateInterpolator()).start(); hideProgressBar(); mWebView.setVisibility(View.VISIBLE); } }, 200); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_detail, menu); if (!showImage) { menu.add(0, 0, 0, "显示全部图片"); } if (fromDB) { menu.findItem(R.id.menu_book_mark).setTitle("取消收藏"); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: mActivity.finish(); break; case R.id.menu_share: shareAction(); break; case R.id.menu_view_in_browser: viewInBrowser(); break; case R.id.menu_reflush: makeRequest(); break; case R.id.menu_font_size: handleFontSize(); break; case R.id.menu_book_mark: doBookmark(item); break; case 0: showAllImage(); break; } return false; } private void showAllImage() { mWebView.loadUrl("javascript:ImageTool.showAllImage()"); } private void nightMode() { mWebView.loadUrl("javascript:BaseTool.setNight(true)"); } public void setCallBack(NewsDetailFragment.NewsDetailCallBack callBack) { this.callBack = callBack; } public void commentAction() { if (callBack != null) { callBack.CommentAction(mNewsItem.getSid(), mNewsItem.getSN(), mNewsItem.getTitle()); } } public void shareAction() { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, mActivity.getString(R.string.share_templates , mNewsItem.getTitle(), Configure.buildArticleUrl(mNewsItem.getSid() + ""))); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mActivity.startActivity(Intent.createChooser(intent, mActivity.getString(R.string.menu_share))); } public void viewInBrowser() { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); Uri content_url = Uri.parse(Configure.buildArticleUrl(mNewsItem.getSid() + "")); intent.setData(content_url); mActivity.startActivity(Intent.createChooser(intent, mActivity.getString(R.string.choise_browser))); } public void handleFontSize() { final DiscreteSeekBar discreteSeekBar = (DiscreteSeekBar) LayoutInflater.from(mActivity).inflate(R.layout.fragment_font_size, null); DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case AlertDialog.BUTTON_POSITIVE: PrefKit.writeInt(getActivity(), "font_size", discreteSeekBar.getProgress()); break; case AlertDialog.BUTTON_NEUTRAL: break; case AlertDialog.BUTTON_NEGATIVE: settings.setTextZoom(100); PrefKit.delete(getActivity(), "font_size"); break; } dialog.dismiss(); } }; discreteSeekBar.setProgress(settings.getTextZoom()); discreteSeekBar.setOnProgressChangeListener(new DiscreteSeekBar.OnProgressChangeListener() { @Override public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) { if (fromUser) { settings.setTextZoom(value); } } @Override public void onStartTrackingTouch(DiscreteSeekBar seekBar) { } @Override public void onStopTrackingTouch(DiscreteSeekBar seekBar) { } }); new AlertDialog.Builder(mActivity).setTitle("字体大小") .setView(discreteSeekBar) .setPositiveButton("保存", listener) .setNegativeButton("默认", listener) .setNeutralButton("取消", listener).create().show(); } public void doBookmark(MenuItem item) { if (hascontent) { String message; Style style; try { if (MyApplication.getInstance().getDbUtils().findById(NewsItem.class, mNewsItem.getSid()) == null) { MyApplication.getInstance().getDbUtils().saveOrUpdate(mNewsItem); message = "收藏成功"; item.setTitle("取消收藏"); fromDB = true; } else { MyApplication.getInstance().getDbUtils().deleteById(NewsItem.class, mNewsItem.getSid()); message = "取消收藏成功"; item.setTitle("收藏"); fromDB = false; } style = CroutonStyle.INFO; } catch (DbException e) { message = "操作失败"; style = Style.ALERT; } Toolkit.showCrouton(mActivity, message, style); } } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && client.myCallback != null) { client.onHideCustomView(); return true; } return false; } private class JavaScriptInterface { Context mContext; JavaScriptInterface(Context c) { mContext = c; } @JavascriptInterface public void showImage(String pos, final String[] imageSrcs) { final int posi; try { posi = Integer.parseInt(pos); myHandler.post(new Runnable() { @Override public void run() { Intent intent = new Intent(mContext, ImageViewActivity.class); intent.putExtra(ImageViewActivity.IMAGE_URLS, imageSrcs); intent.putExtra(ImageViewActivity.CURRENT_POS, posi); mContext.startActivity(intent); } }); } catch (Exception e) { Log.d(getClass().getName(), "Illegal argument"); } } @JavascriptInterface public void loadSohuVideo(final String hoder_id, final String requestUrl) { myHandler.post(new Runnable() { @Override public void run() { NetKit.getAsyncClient().get(requestUrl, new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONObject response) { try { mWebView.loadUrl("javascript:VideoTool.VideoCallBack(\"" + hoder_id + "\",\"" + response.getJSONObject("data").getString("url_high_mp4") + "\",\"" + response.getJSONObject("data").getString("hor_big_pic") + "\")"); } catch (Exception e) { Toolkit.showCrouton(mActivity, "搜狐视频加载失败", Style.ALERT); } } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) { Toolkit.showCrouton(mActivity, "搜狐视频加载失败", Style.ALERT); if (MyApplication.getInstance().getDebug()) { Toast.makeText(getActivity(), throwable.toString(), Toast.LENGTH_SHORT).show(); } } }); } }); } @JavascriptInterface public void showMessage(final String message, final String type) { myHandler.post(new Runnable() { @Override public void run() { Toolkit.showCrouton(mActivity, message, CroutonStyle.getStyle(type)); } }); } } class MyWebViewClient extends WebViewClient { private static final String TAG = "WebView ImageLoader"; private boolean finish = false; @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { finish = false; super.onPageStarted(view, url, favicon); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { try { Intent intent; Matcher sidMatcher = Configure.ARTICLE_PATTERN.matcher(url); if (sidMatcher.find()) { intent = new Intent(mActivity, NewsDetailActivity.class); intent.putExtra(NewsDetailFragment.NEWS_SID_KEY, Integer.parseInt(sidMatcher.group(1))); intent.putExtra(NewsDetailFragment.NEWS_TITLE_KEY, ""); mActivity.startActivity(intent); mActivity.finish(); } else { intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setData(Uri.parse(url)); mActivity.startActivity(intent); } } catch (Exception ignored) { } return true; } @Override public void onPageFinished(WebView view, String url) { System.out.println("MyWebViewClient.onPageFinished"); super.onPageFinished(view, url); finish = true; } @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { System.out.println("MyWebViewClient.shouldInterceptRequest(view,url) url = [" + url + "]"); String prefix = MimeTypeMap.getFileExtensionFromUrl(url); if (!TextUtils.isEmpty(prefix)) { String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(prefix); if (mimeType != null && mimeType.startsWith("image")) { if (finish || showImage) { File image = ImageLoader.getInstance().getDiskCache().get(url); if (image != null) { System.out.println("load Image From disk cache"); try { return new WebResourceResponse(mimeType, "UTF-8", new FileInputStream(image)); } catch (FileNotFoundException ignored) { } } else { System.out.println("load Image From net"); } } else { System.out.println("Load Image Hoder"); try { return new WebResourceResponse("image/svg+xml", "UTF-8", mActivity.getAssets().open("image.svg")); } catch (IOException ignored) { } } } else { System.out.println("load other resourse"); } } return super.shouldInterceptRequest(view, url); } } class VideoWebChromeClient extends WebChromeClient { private View myView = null; CustomViewCallback myCallback = null; @Override public void onShowCustomView(View view, CustomViewCallback customViewCallback) { if (myCallback != null) { myCallback.onCustomViewHidden(); myCallback = null; return; } view.setBackgroundColor(Color.BLACK); onShowHtmlVideoView(view); myView = view; myCallback = customViewCallback; } @Override public void onHideCustomView() { if (myView != null) { if (myCallback != null) { myCallback.onCustomViewHidden(); myCallback = null; } onHideHtmlVideoView(myView); myView = null; } } } private void onShowHtmlVideoView(View html5VideoView) { if (callBack != null) { callBack.onVideoFullScreen(true); callBack.onShowHtmlVideoView(html5VideoView); } else { ViewGroup parent = (ViewGroup) mActivity.findViewById(R.id.content); parent.addView(html5VideoView); } mWebView.setVisibility(View.GONE); mActionButtom.setVisibility(View.GONE); } private void onHideHtmlVideoView(View html5VideoView) { if (callBack != null) { callBack.onVideoFullScreen(false); callBack.onHideHtmlVideoView(html5VideoView); } else { ViewGroup parent = (ViewGroup) mActivity.findViewById(R.id.content); parent.removeView(html5VideoView); } mWebView.setVisibility(View.VISIBLE); mActionButtom.setVisibility(View.VISIBLE); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mWebView.loadUrl("javascript:BaseTool.updateWidth()"); } }