package com.jasonchen.microlang.activitys; import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.DialogFragment; import android.support.v4.widget.SwipeRefreshLayout; import android.util.TypedValue; import android.view.View; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; import com.jasonchen.microlang.R; import com.jasonchen.microlang.beans.AccountBean; import com.jasonchen.microlang.beans.UserBean; import com.jasonchen.microlang.dao.BlackOAuthDao; import com.jasonchen.microlang.dao.OAuthDao; import com.jasonchen.microlang.database.AccountDBTask; import com.jasonchen.microlang.debug.AppLogger; import com.jasonchen.microlang.exception.WeiboException; import com.jasonchen.microlang.swipeback.app.SwipeBackActivity; import com.jasonchen.microlang.tasks.MyAsyncTask; import com.jasonchen.microlang.utils.StreamUtility; import com.jasonchen.microlang.utils.Utility; import com.jasonchen.microlang.utils.ViewUtility; import com.jasonchen.microlang.utils.http.URLHelper; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import java.util.HashMap; import java.util.Map; import me.drakeet.materialdialog.MaterialDialog; /** * jasonchen * 2015/04/10 */ public class BlackMagicActivity extends SwipeBackActivity implements SwipeRefreshLayout.OnRefreshListener { private SwipeRefreshLayout container; private WebView webView; private String code; private MyHandler handler; private static final int START_OAUTH_TASK = 0; @SuppressWarnings("deprecation") @Override public void onCreate(Bundle savedInstanceState) { mLayout = R.layout.activity_oauth; super.onCreate(savedInstanceState); initView(); } private void initView() { container = ViewUtility.findViewById(this, R.id.container); webView = ViewUtility.findViewById(this, R.id.webView); webView.setWebViewClient(new WeiboWebViewClient()); handler = new MyHandler(this); getSupportActionBar().setTitle(getString(R.string.oauth)); container.setColorSchemeColors(getResources().getColor(R.color.colorPrimary)); container.setOnRefreshListener(this); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setSaveFormData(false); settings.setSavePassword(false); settings.setCacheMode(WebSettings.LOAD_NO_CACHE); settings.setRenderPriority(WebSettings.RenderPriority.HIGH); settings.setLoadWithOverviewMode(true); settings.setUseWideViewPort(true); CookieSyncManager.createInstance(this); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.removeAllCookie(); refresh(); } @Override protected void onResume() { super.onResume(); } @Override protected void onDestroy() { super.onDestroy(); webView.clearCache(true); webView = null; handler = null; } public void refresh() { webView.clearView(); webView.loadUrl("about:blank"); webView.loadUrl(getWeiboOAuthUrl()); container.setProgressViewOffset(false, 0, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48, getResources().getDisplayMetrics())); container.setRefreshing(true); } private void completeRefresh() { container.setRefreshing(false); } @Override public void onRefresh() { refresh(); } static class MyHandler extends Handler { WeakReference<BlackMagicActivity> mActivity; MyHandler(BlackMagicActivity activity) { mActivity = new WeakReference<BlackMagicActivity>(activity); } @Override public void handleMessage(Message msg) { final BlackMagicActivity activity = mActivity.get(); super.handleMessage(msg); if (START_OAUTH_TASK == msg.what) { @SuppressWarnings("unchecked") Map<String, String> map = (Map<String, String>) msg.obj; String access_token = map.get("access_token"); String expires_time = map.get("expires_in"); new OAuthTask(activity).execute(access_token, expires_time); } } } private String getWeiboOAuthUrl() { Map<String, String> parameters = new HashMap<String, String>(); parameters.put("client_id", URLHelper.HACK_APP_KEY); parameters.put("response_type", "code"); parameters.put("redirect_uri", URLHelper.HACK_DIRECT_URL); parameters.put("display", "mobile"); return URLHelper.URL_OAUTH2_ACCESS_AUTHORIZE + "?" + Utility.encodeUrl(parameters) + "&scope=email,direct_messages_read,direct_messages_write,friendships_groups_read,friendships_groups_write,statuses_to_me_read,invitation_write"; } private String getWeiboTokenUrl() { Map<String, String> parameters = new HashMap<String, String>(); parameters.put("client_id", URLHelper.HACK_APP_KEY); parameters.put("client_secret", URLHelper.HACK_APP_SECRET); parameters.put("grant_type", "authorization_code"); parameters.put("redirect_uri", URLHelper.HACK_DIRECT_URL); parameters.put("code", code); return URLHelper.ACESS_TOKEN + "?" + Utility.encodeUrl(parameters); } private class WeiboWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { if (url.startsWith(URLHelper.HACK_DIRECT_URL)) { handleRedirectUrl(view, url); view.stopLoading(); return; } super.onPageStarted(view, url, favicon); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); final MaterialDialog showErrorDialog = new MaterialDialog(BlackMagicActivity.this); showErrorDialog.setTitle(getString(R.string.notice)); showErrorDialog.setMessage(getString(R.string.sina_server_error)) .setPositiveButton(getString(R.string.confirm), new View.OnClickListener() { @Override public void onClick(View v) { showErrorDialog.dismiss(); finish(); overridePendingTransition(R.anim.stay, R.anim.push_right_out); } }); showErrorDialog.show(); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); if (!url.equals("about:blank")) { completeRefresh(); } } } private void handleRedirectUrl(WebView view, String url) { Bundle values = Utility.parseUrl(url); String error = values.getString("error"); String error_code = values.getString("error_code"); code = values.getString("code"); final Bundle newValues = new Bundle(); final Intent intent = new Intent(); intent.putExtras(newValues); if (error == null && error_code == null && code != null) { new Thread() { public void run() { try { URL url = new URL(getWeiboTokenUrl()); HttpURLConnection conn; conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(4000); conn.setRequestMethod("POST"); int responce_code = conn.getResponseCode(); if (responce_code == 200) { InputStream is = conn.getInputStream(); String result = StreamUtility.readFromStream(is); JSONObject obj = new JSONObject(result); String access_token = obj.getString("access_token"); String expires_time = obj.getString("expires_in"); newValues.putString("access_token", access_token); newValues.putString("expires_in", expires_time); System.out.println("token:" + access_token + ",expires:" + expires_time); setResult(RESULT_OK, intent); Map<String, String> map = new HashMap<String, String>(); map.put("access_token", access_token); map.put("expires_in", expires_time); Message msg = Message.obtain(); msg.what = START_OAUTH_TASK; msg.obj = map; handler.sendMessage(msg); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } } ; }.start(); System.out.println("code:" + code); } else { Toast.makeText(BlackMagicActivity.this, getString(R.string.you_cancel_login), Toast.LENGTH_SHORT) .show(); finish(); overridePendingTransition(R.anim.stay, R.anim.push_right_out); } } @Override public void onBackPressed() { super.onBackPressed(); if (webView.canGoBack()) { webView.goBack(); } else { Toast.makeText(BlackMagicActivity.this, getString(R.string.you_cancel_login), Toast.LENGTH_SHORT) .show(); finish(); overridePendingTransition(R.anim.stay, R.anim.push_right_out); } } private static class OAuthTask extends MyAsyncTask<String, UserBean, BlackMagicActivity.DBResult> { private WeiboException e; private ProgressFragment progressFragment = ProgressFragment .newInstance(); private WeakReference<BlackMagicActivity> oAuthActivityWeakReference; private OAuthTask(BlackMagicActivity activity) { oAuthActivityWeakReference = new WeakReference<BlackMagicActivity>( activity); } @Override protected void onPreExecute() { progressFragment.setAsyncTask(this); BlackMagicActivity activity = oAuthActivityWeakReference.get(); if (activity != null) { progressFragment.show(activity.getSupportFragmentManager(), ""); } } @Override protected BlackMagicActivity.DBResult doInBackground(String... params) { String token = params[0]; long expiresInSeconds = Long.valueOf(params[1]); try { UserBean user = new BlackOAuthDao(token).getOAuthUserInfo(); AccountBean account = new AccountBean(); account.setAccess_token_secret(token); account.setExpires_time_secret(System.currentTimeMillis() + expiresInSeconds * 1000); account.setInfo(user); AppLogger.e("token expires in " + Utility.calcTokenExpiresInDays(account) + " days"); return AccountDBTask.addOrUpdateBlackAccount(account, true); } catch (WeiboException e) { AppLogger.e(e.getError()); this.e = e; cancel(true); return null; } } @Override protected void onCancelled(BlackMagicActivity.DBResult dbResult) { super.onCancelled(dbResult); if (progressFragment != null) { progressFragment.dismissAllowingStateLoss(); } BlackMagicActivity activity = oAuthActivityWeakReference.get(); if (activity == null) { return; } if (e != null) { Toast.makeText(activity, e.getError(), Toast.LENGTH_SHORT) .show(); } activity.webView.loadUrl(activity.getWeiboOAuthUrl()); } @Override protected void onPostExecute(BlackMagicActivity.DBResult dbResult) { if (progressFragment.isVisible()) { progressFragment.dismissAllowingStateLoss(); } BlackMagicActivity activity = oAuthActivityWeakReference.get(); if (activity == null) { return; } switch (dbResult) { case add_successfuly: Toast.makeText(activity, activity.getString(R.string.login_success), Toast.LENGTH_SHORT).show(); break; case update_successfully: Toast.makeText(activity, activity.getString(R.string.update_account_success), Toast.LENGTH_SHORT).show(); break; } activity.finish(); activity.overridePendingTransition(R.anim.stay, R.anim.push_right_out); } } @Override protected void onPause() { super.onPause(); if (isFinishing()) { webView.stopLoading(); } } public static class ProgressFragment extends DialogFragment { MyAsyncTask asyncTask = null; public static ProgressFragment newInstance() { ProgressFragment frag = new ProgressFragment(); frag.setRetainInstance(true); Bundle args = new Bundle(); frag.setArguments(args); return frag; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { ProgressDialog dialog = new ProgressDialog(getActivity()); dialog.setMessage(getString(R.string.oauthing)); dialog.setIndeterminate(false); dialog.setCancelable(true); return dialog; } @Override public void onCancel(DialogInterface dialog) { if (asyncTask != null) { asyncTask.cancel(true); } super.onCancel(dialog); } void setAsyncTask(MyAsyncTask task) { asyncTask = task; } } public static enum DBResult { add_successfuly, update_successfully } }