以前的微博认证,都是使用WebView打开授权页面,当新浪推出SSO认证后,腾讯也紧接着出现SSO。所谓SSO认证,通俗的一点讲就是,自己写的app需要使用新浪或腾讯微进行分享、发表微博等操作。如果用户的手机客户端安装了符合SSO认证的新浪、腾讯等微博客户端版本且已登录,则会自动启动新浪、腾讯等微博客户端进行授权,无需进行输入账号、密码。比较方便快捷,当然也有一些用户并未装符合要求的微博或者未安装新浪、腾讯微博客户端,这个时候该怎么办。不必担心,不需要自己去写WebView去加载授权页面,新浪、腾讯微博SDK都已封装好了,他们的SDK里面已经完成了这些操作。新浪微博使用的dialog加载的授权页面,而腾讯使用的是Activity加载的授权页面。无论双方方式是否有什么不同,最终的结果是一样的。
好了,废话不多说了,下面介绍一下腾讯微博SDK需要注意的一些地方。腾讯微博认证的加载的Activity是Authorize.java,这个类需要做适当的修改可以避免一下问题。
附上腾讯微博SDK源码及API调用demo下载地址:http://download.csdn.net/detail/hap_gx/5573179
1、注释下面这行代码,主要是避免全屏加载,影响通知栏的显示。
// getWindow().setFlags(
// WindowManager.LayoutParams.FLAG_FULLSCREEN,
// WindowManager.LayoutParams.FLAG_FULLSCREEN);
2、在AndroidMainFest.xml文件中添加如下设置,是为了避免Authorize这个Activity在横竖拼切换时出现的空指针异常。出现这个异常主要是由于在从config.properties文件中获取app_id,app_key,return_url等值。 并不是这样做了就会避免这种错误,我在使用友盟打包工具打渠道包时,发现打出来的70个渠道包都是存在这个严重的问题。如果想绝对避免这个空指针异常,最好的办法是将app_id,app_key,return_url等值直接写在代码中,删掉这个方法,不使用config.properties保存这些值。
java.lang.NullPointerExceptionat
java.util.Properties.load(Properties.java:290)
at com.tencent.weibo.sdk.android.api.util.Util.getConfig(Util.java:295)
clientId = Util.getConfig().getProperty("APP_KEY");
redirectUri = Util.getConfig().getProperty("REDIRECT_URI");
这个方法主要是从config.properties文件中获取Properties对象,然后根据key获取值值。
* @des 得到config.properties配置文件中的所有配置/**
* @return Properties对象
*/
public static Properties getConfig() {
Properties props = new Properties();
InputStream in = Util.class
.getResourceAsStream("/config/config.properties");
try {
props.load(in);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("工具包异常", "获取配置文件异常");
e.printStackTrace();
}
return props;
}<activity android:name="com.tencent.weibo.sdk.android.component.Authorize" android:configChanges="orientation|keyboardHidden|locale" android:screenOrientation="portrait"> </activity>
3、腾讯微博授权页面加载,输入账号密码后,点击授权,部分设备会出现先跳到你给定的return_url网页上去,然后才会授权完成,关闭授权页面,所用时间会比较长。重要原因是腾讯微博SSO认证源码是在OnPageFinished的时候去做解析保存数据的操作,比较慢,最好是在OnPageStarted的时候就做这个操作,就可以避免部分设备跳到return_url的网页。应该为下面的代码:
webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { // TODO Auto-generated method stub // super.onPageFinished(view, url); Log.d("backurl", "onPageFinished:" +url); // 此处不适合做解析,保存数据等操作,最好是在onPageStarted // if (url.indexOf("access_token") != -1 && !isShow) { // jumpResultParser(url); // } if (dialog != null && dialog.isShowing()) { dialog.cancel(); } } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { if (url.indexOf("access_token") != -1 && !isShow) { jumpResultParser(url); } super.onPageStarted(view, url, favicon); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Log.d("backurl", "shouldOverrideUrlLoading:" + url); if (url.indexOf("access_token") != -1 && !isShow) { jumpResultParser(url); return true; } return false; } });
最后附上Authorize.java代码
package com.tencent.weibo.sdk.android.component; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.Window; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.tencent.weibo.sdk.android.api.util.BackGroudSeletor; import com.tencent.weibo.sdk.android.api.util.Util; /** * 用户授权组件 * * * */ public class Authorize extends Activity { WebView webView; String _url; String _fileName; public static int WEBVIEWSTATE_1 = 0; int webview_state = 0; String path; Dialog _dialog; public static final int ALERT_DOWNLOAD = 0; public static final int ALERT_FAV = 1; public static final int PROGRESS_H = 3; public static final int ALERT_NETWORK = 4; private ProgressDialog dialog; private LinearLayout layout = null; private String redirectUri; private String clientId ; private boolean isShow = false; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); if (!Util.isNetworkAvailable(this)) { Authorize.this.showDialog(ALERT_NETWORK); } else { DisplayMetrics displaysMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaysMetrics); String pix = displaysMetrics.widthPixels + "x" + displaysMetrics.heightPixels; BackGroudSeletor.setPix(pix); try { // Bundle bundle = getIntent().getExtras(); clientId = Util.getConfig().getProperty("APP_KEY");// bundle.getString("APP_KEY"); redirectUri = Util.getConfig().getProperty("REDIRECT_URI");// bundle.getString("REDIRECT_URI"); if (clientId == null || "".equals(clientId) || redirectUri == null || "".equals(redirectUri)) { Toast.makeText(Authorize.this, "请在配置文件中填写相应的信息", Toast.LENGTH_SHORT).show(); } Log.d("redirectUri", redirectUri); // getWindow().setFlags( // WindowManager.LayoutParams.FLAG_FULLSCREEN, // WindowManager.LayoutParams.FLAG_FULLSCREEN); requestWindowFeature(Window.FEATURE_NO_TITLE); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); int state = (int) Math.random() * 1000 + 111; path = "https://open.t.qq.com/cgi-bin/oauth2/authorize?client_id=" + clientId + "&response_type=token&redirect_uri=" + redirectUri + "&state=" + state; this.initLayout(); } catch (Exception e) { e.printStackTrace(); } } } /** * 初始化界面使用控件,并设置相应监听 * */ public void initLayout() { RelativeLayout.LayoutParams fillParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT); RelativeLayout.LayoutParams fillWrapParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams wrapParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); dialog = new ProgressDialog(this); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setMessage("请稍后..."); dialog.setIndeterminate(false); dialog.setCancelable(false); dialog.show(); layout = new LinearLayout(this); layout.setLayoutParams(fillParams); layout.setOrientation(LinearLayout.VERTICAL); layout.setBackgroundColor(Color.WHITE); RelativeLayout cannelLayout = new RelativeLayout(this); cannelLayout.setLayoutParams(fillWrapParams); cannelLayout.setBackgroundDrawable(BackGroudSeletor.getdrawble( "up_bg2x", getApplication())); cannelLayout.setGravity(LinearLayout.HORIZONTAL); Button returnBtn = new Button(this); String[] pngArray = { "quxiao_btn2x", "quxiao_btn_hover" }; returnBtn.setBackgroundDrawable(BackGroudSeletor.createBgByImageIds( pngArray, getApplication())); returnBtn.setText("取消"); wrapParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE); wrapParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE); wrapParams.leftMargin = 10; wrapParams.topMargin = 10; wrapParams.bottomMargin = 10; returnBtn.setLayoutParams(wrapParams); returnBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Authorize.this.finish(); } }); cannelLayout.addView(returnBtn); TextView title = new TextView(this); title.setText("授权"); title.setTextColor(Color.WHITE); title.setTextSize(24f); RelativeLayout.LayoutParams titleParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); titleParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); title.setLayoutParams(titleParams); cannelLayout.addView(title); layout.addView(cannelLayout); webView = new WebView(this); LinearLayout.LayoutParams wvParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); webView.setLayoutParams(wvParams); WebSettings webSettings = webView.getSettings(); webView.setVerticalScrollBarEnabled(false); webSettings.setJavaScriptEnabled(true); webSettings.setUseWideViewPort(true); webSettings.setLoadWithOverviewMode(false); webView.loadUrl(path); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); Log.d("newProgress", newProgress + ".."); // if (dialog!=null&& !dialog.isShowing()) { // dialog.show(); // } } }); webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { // TODO Auto-generated method stub // super.onPageFinished(view, url); Log.d("backurl", "onPageFinished:" +url); // 此处不适合做解析,保存数据等操作,最好是在onPageStarted // if (url.indexOf("access_token") != -1 && !isShow) { // jumpResultParser(url); // } if (dialog != null && dialog.isShowing()) { dialog.cancel(); } } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { if (url.indexOf("access_token") != -1 && !isShow) { jumpResultParser(url); } super.onPageStarted(view, url, favicon); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.indexOf("access_token") != -1 && !isShow) { jumpResultParser(url); return true; } return false; } }); layout.addView(webView); this.setContentView(layout); } /** * * 获取授权后的返回地址,并对其进行解析 */ public void jumpResultParser(String result) { String resultParam = result.split("#")[1]; String params[] = resultParam.split("&"); String accessToken = params[0].split("=")[1]; String expiresIn = params[1].split("=")[1]; String openid = params[2].split("=")[1]; String openkey = params[3].split("=")[1]; String refreshToken = params[4].split("=")[1]; String state = params[5].split("=")[1]; String name = params[6].split("=")[1]; String nick = params[7].split("=")[1]; Context context = this.getApplicationContext(); if (accessToken != null && !"".equals(accessToken)) { Util.saveSharePersistent(context, "ACCESS_TOKEN", accessToken); Util.saveSharePersistent(context, "EXPIRES_IN", expiresIn);// accesstoken过期时间,以返回的时间的准,单位为秒,注意过期时提醒用户重新授权 Util.saveSharePersistent(context, "OPEN_ID", openid); Util.saveSharePersistent(context, "OPEN_KEY", openkey); Util.saveSharePersistent(context, "REFRESH_TOKEN", refreshToken); Util.saveSharePersistent(context, "NAME", name); Util.saveSharePersistent(context, "NICK", nick); Util.saveSharePersistent(context, "CLIENT_ID", clientId); Util.saveSharePersistent(context, "AUTHORIZETIME", String.valueOf(System.currentTimeMillis() / 1000l)); // Toast.makeText(Authorize.this, "授权成功", Toast.LENGTH_SHORT).show(); isShow = true; } this.finish(); } Handler handle = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch (msg.what) { case 100: // Log.i("showDialog", "showDialog"); Authorize.this.showDialog(ALERT_NETWORK); break; } } }; @Override protected Dialog onCreateDialog(int id) { switch (id) { case PROGRESS_H: _dialog = new ProgressDialog(this); ((ProgressDialog) _dialog).setMessage("加载中..."); break; case ALERT_NETWORK: AlertDialog.Builder builder2 = new AlertDialog.Builder(this); builder2.setTitle("网络连接异常,是否重新连接?"); builder2.setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (Util.isNetworkAvailable(Authorize.this)) { webView.loadUrl(path); } else { Message msg = Message.obtain(); msg.what = 100; handle.sendMessage(msg); } } }); builder2.setNegativeButton("否", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Authorize.this.finish(); } }); _dialog = builder2.create(); break; } return _dialog; } }