package org.aisen.weibo.sina.ui.fragment.account; import android.app.Activity; import android.app.Fragment; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import org.aisen.android.common.context.GlobalContext; import org.aisen.android.common.setting.SettingUtility; import org.aisen.android.common.utils.FileUtils; import org.aisen.android.common.utils.Logger; import org.aisen.android.common.utils.ViewUtils; import org.aisen.android.network.http.Params; import org.aisen.android.network.http.ParamsUtil; import org.aisen.android.network.task.TaskException; import org.aisen.android.network.task.WorkTask; import org.aisen.android.support.inject.ViewInject; import org.aisen.android.ui.activity.basic.BaseActivity; import org.aisen.android.ui.activity.container.FragmentArgs; import org.aisen.android.ui.fragment.ABaseFragment; import org.aisen.weibo.sina.R; import org.aisen.weibo.sina.sinasdk.SinaSDK; import org.aisen.weibo.sina.sinasdk.bean.AccessToken; import org.aisen.weibo.sina.sinasdk.bean.Groups; import org.aisen.weibo.sina.sinasdk.bean.WeiBoUser; import org.aisen.weibo.sina.support.bean.AccountBean; import org.aisen.weibo.sina.support.utils.ThemeUtils; import org.aisen.weibo.sina.support.utils.UMengUtil; import org.aisen.weibo.sina.ui.activity.base.SinaCommonActivity; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; /** * 网页授权页面 * * Created by wangdan on 15/12/31. */ public class WebLoginFragment extends ABaseFragment { public static final String TAG = "Fragment-Login"; public enum Client { aisen, weico } public static void launch(Activity from, Client client, String account, String password, int requestCode) { FragmentArgs args = new FragmentArgs(); args.add("client", client.toString()); if (!TextUtils.isEmpty(account) && !TextUtils.isEmpty(password)) { args.add("account", account); args.add("password", password); } SinaCommonActivity.launchForResult(from, WebLoginFragment.class, args, requestCode); } public static void launch(Fragment from, Client client, String account, String password, int requestCode) { FragmentArgs args = new FragmentArgs(); args.add("client", client.toString()); if (!TextUtils.isEmpty(account) && !TextUtils.isEmpty(password)) { args.add("account", account); args.add("password", password); } SinaCommonActivity.launchForResult(from, WebLoginFragment.class, args, requestCode); } @ViewInject(id = R.id.webview) WebView mWebView; @ViewInject(id = R.id.progressbar) ProgressBar mProgressBar; private Client mClient; private String mAccount = ""; private String mPassword = ""; private boolean mAccountFilled = false; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); BaseActivity activity = (BaseActivity) getActivity(); activity.getSupportActionBar().setTitle(R.string.login_title); activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mClient = Client.valueOf(getArguments().getString("client")); if (getArguments().containsKey("account")) { mAccount = getArguments().getString("account"); } if (getArguments().containsKey("password")) { mPassword = getArguments().getString("password"); } } @Override public int inflateContentView() { return R.layout.ui_login; } @Override protected void layoutInit(LayoutInflater inflater, Bundle savedInstanceSate) { super.layoutInit(inflater, savedInstanceSate); WebSettings setting = mWebView.getSettings(); setting.setJavaScriptEnabled(true); setting.setDomStorageEnabled(true); setting.setAppCacheEnabled(true); setting.setDefaultTextEncodingName("utf-8") ; mWebView.addJavascriptInterface(new LoginJavaScriptInterface(), "loginjs"); mWebView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, final String url) { // 授权成功 if (url != null && url.startsWith(getClientCallback())) { Params params = ParamsUtil.deCodeUrl(url); String code = params.getParameter("code"); if (isActivityRunning() && mLoadAccountTask == null) { Logger.d(TAG, "授权成功, code = " + code); // 把WebView隐藏,因为callback页面是个错误的页面 mWebView.setVisibility(View.INVISIBLE); mLoadAccountTask = new LoadAccountTask(); mLoadAccountTask.execute(code); } } if (!TextUtils.isEmpty(url) && !url.startsWith("sinaweibo://")) { view.loadUrl(url); } Logger.d(TAG, "load url = %s", view.getUrl()); return true; } }); mWebView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress < 100) { mProgressBar.setVisibility(View.VISIBLE); mProgressBar.setProgress(newProgress); Logger.d(TAG, "progress = %d , url = %s", newProgress, view.getUrl()); } else if (newProgress == 100) { mProgressBar.setVisibility(View.GONE); Logger.d(TAG, "progress = 100 , url = %s", view.getUrl()); // 填充账号 if (!TextUtils.isEmpty(mAccount) && !TextUtils.isEmpty(mPassword)) { if (!mAccountFilled && !TextUtils.isEmpty(view.getUrl()) && view.getUrl().equalsIgnoreCase("about:blank")) { Logger.d(TAG, "fillAccount(%s, %s)", mAccount, mPassword); mWebView.loadUrl("javascript:fillAccount()"); mAccountFilled = true; } } } super.onProgressChanged(view, newProgress); } }); } @Override public void requestData() { super.requestData(); new LoadHtmlTask().execute(); } final class LoginJavaScriptInterface { public LoginJavaScriptInterface() { Logger.d(TAG, "new LoginJavaScriptInterface()"); } @JavascriptInterface public void setAccount(String account, String password) { Logger.d(TAG, "account = %s, password = %s", account, password); mAccount = account; mPassword = password; } } /** * 抓取网页,填充账户密码,且通过JS注入,获取正确的账户密码保存在手机备下次使用 */ class LoadHtmlTask extends ABaseTask<Void, Void, String> { public LoadHtmlTask() { super("LoadHtmlTask"); } @Override public String workInBackground(Void... params) throws TaskException { int count = 3; while (count-- >= 0) { try { String js = FileUtils.readAssetsFile("oauth.js", GlobalContext.getInstance()); js = js.replace("%username%", mAccount).replace("%password%", mPassword); Document dom = Jsoup.connect(getLoginUrl()).get(); String html = dom.toString(); html = html.replace("<html>", "<html id='all' >").replace("</head>", js + "</head>") .replace("action-type=\"submit\"", "action-type=\"submit\" id=\"submit\""); // 通过监听input标签的oninput事件,来获取账户密码 // onchange是value改变,且焦点改变才触发 // oninput是value改变就触发 try { dom = Jsoup.parse(html); Element inputAccount = dom.select("input#userId").first(); inputAccount.attr("oninput", "getAccount()"); Element pwdAccount = dom.select("input#passwd").first(); pwdAccount.attr("oninput", "getAccount()"); Logger.d(TAG, inputAccount.toString()); Logger.d(TAG, pwdAccount.toString()); html = dom.toString(); Logger.d(TAG, "添加input监听事件"); } catch (Throwable e) { e.printStackTrace(); } Logger.v(TAG, html); return html; } catch (Exception e) { e.printStackTrace(); } } throw new TaskException("", GlobalContext.getInstance().getResources().getString(R.string.login_html_faild)); } @Override protected void onSuccess(String s) { super.onSuccess(s); if (isActivityRunning()) { // 加载网页 mWebView.loadDataWithBaseURL("https://api.weibo.com", s, "text/html", "UTF-8", ""); } } } /** * 1、获取授权的TOKEN * 2、加载用户信息 * 3、加载分组信息 */ LoadAccountTask mLoadAccountTask; class LoadAccountTask extends WorkTask<String, Integer, AccountBean> { LoadAccountTask() { mLoadAccountTask = this; } @Override protected void onPrepare() { super.onPrepare(); ViewUtils.createProgressDialog(getActivity(), getString(R.string.login_loading_token), ThemeUtils.getThemeColor()).show(); } @Override public AccountBean workInBackground(String... params) throws TaskException { AccountBean account = new AccountBean(); account.setAccount(mAccount); account.setPassword(mPassword); // 1、请求授权 AccessToken accessToken = null; if (mClient == Client.aisen) { accessToken = SinaSDK.getInstance(null).getAccessToken(params[0]); } else { accessToken = SinaSDK.getInstance(null).getWeicoAccessToken(params[0]); } accessToken.setAppKey(getClientKey()); accessToken.setAppScreet(getClientScreet()); account.setAccessToken(accessToken); Logger.d(TAG, "加载Token[%s]", accessToken.getToken()); if (mClient == Client.aisen) { // 2、加载用户信息 publishProgress(R.string.login_loading_userinfo); WeiBoUser user = SinaSDK.getInstance(accessToken).userShow(accessToken.getUid(), null); account.setUser(user); account.setUid(user.getIdstr()); Logger.d(TAG, "加载用户[%s]", user.getScreen_name()); // 3、加载分组信息 publishProgress(R.string.login_loading_groups); Groups groups = SinaSDK.getInstance(accessToken).friendshipGroups(); account.setGroups(groups); Logger.d(TAG, "加载分组[%d]个", groups.getLists().size()); } return account; } @Override protected void onSuccess(AccountBean accountBean) { super.onSuccess(accountBean); if (isActivityRunning()) { showMessage(R.string.login_success); Logger.d(TAG, "授权成功"); Intent data = new Intent(); data.putExtra("account", accountBean); getActivity().setResult(Activity.RESULT_OK, data); } } @Override protected void onFailure(TaskException exception) { super.onFailure(exception); if (isActivityRunning()) { showMessage(R.string.login_faild); Logger.d(TAG, "授权失败 " + exception.getMessage()); getActivity().setResult(Activity.RESULT_CANCELED); } } @Override protected void onFinished() { super.onFinished(); ViewUtils.dismissProgressDialog(); if (isActivityRunning()) { getActivity().finish(); } } } private String getLoginUrl() { if (mClient == Client.weico) { return String .format("https://api.weibo.com/oauth2/authorize?client_id=%s&redirect_uri=%s&display=mobile&forcelogin=true", getClientKey(), getClientCallback()); } return String .format("https://api.weibo.com/oauth2/authorize?client_id=%s&scope=friendships_groups_read,friendships_groups_write,statuses_to_me_read,follow_app_official_microblog&redirect_uri=%s&display=mobile&forcelogin=true", getClientKey(), getClientCallback()); } private String getClientKey() { if (mClient == Client.weico) { return SettingUtility.getStringSetting("weico_key"); } return "2362431378"; } public String getClientScreet() { if (mClient == Client.weico) { return SettingUtility.getStringSetting("weico_screet"); } return "582ce3cdcdeb8a3b45087073d0dbcadf"; } private String getClientCallback() { if (mClient == Client.weico) { return SettingUtility.getStringSetting("weico_callback"); } return "http://boyqiang520.s8.csome.cn/oauth2/"; } @Override public void onResume() { super.onResume(); UMengUtil.onPageStart(getActivity(), String.format("%s授权页", mClient == Client.weico ? "Weico" : "Aisen")); } @Override public void onPause() { super.onPause(); UMengUtil.onPageEnd(getActivity(), String.format("%s授权页", mClient == Client.weico ? "Weico" : "Aisen")); } }