以前的微博认证,都是使用WebView打开授权页面,当新浪推出SSO认证后,腾讯也紧接着出现SSO。所谓SSO认证,通俗的一点讲就是,自己写的app需要使用新浪或腾讯微进行分享、发表微博等操作。如果用户的手机客户端安装了符合SSO认证的新浪、腾讯等微博客户端版本且已登录,则会自动启动新浪、腾讯等微博客户端进行授权,无需进行输入账号、密码。比较方便快捷,当然也有一些用户并未装符合要求的微博或者未安装新浪、腾讯微博客户端,这个时候该怎么办。不必担心,不需要自己去写WebView去加载授权页面,新浪、腾讯微博SDK都已封装好了,他们的SDK里面已经完成了这些操作。新浪微博使用的dialog加载的授权页面,而腾讯使用的是Activity加载的授权页面。无论双方方式是否有什么不同,最终的结果是一样的。
好了,废话不多说了,下面介绍一下腾讯微博SDK需要注意的一些地方。腾讯微博认证的加载的Activity是Authorize.java,这个类需要做适当的修改可以避免一下问题。
附上腾讯微博SDK源码及API调用demo下载地址:http://download.youkuaiyun.com/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;
}
}