通常在应用开发中,非常常用的一个功能就是应用的三方登陆功能,要实现第三方登陆,一般我们都会是下载相应平台 的sdk 进行集成进来进行开发,同时,在Mob 官网上也提供了三方登陆的集成方式
官方Demo:
ThirdPartyLoginDemo
实现步骤:
① 授权:
Platform weibo = ShareSDK.getPlatform(SinaWeibo.NAME);
weibo.setPlatformActionListener(paListener);
weibo.authorize();
//移除授权
//weibo.removeAccount(true);
调用authorize方法,会弹出一个基于ShareSDKUIShell的授权页面,填写账号和密码以后,会执行授权操作。这个方法的操作回调paListener并不实际带回什么数据,只是通过回调告知外部成功或者失败。
同时,这里也是需要修改assets目录下的ShareSDK.xml
② 获取三方资料:
上面只是完成了授权操作,但是并不会带回 实际的数据,那么一般我们都是需要带回用户的第三方信息的,那么这里就不是调用authorize()
,而是showUser(null)
Platform weibo = ShareSDK.getPlatform(SinaWeibo.NAME);
weibo.setPlatformActionListener(paListener);
weibo.showUser(null);//获取用户资料
这里传递了一个paListener
.接口方法
void onComplete(Platform platform, int action, HashMap<String, Object> res);
void onError(Platform platform, int action, Throwable t);
void onCancel(Platform platform, int action);
注意事项
Platform weibo = ShareSDK.getPlatform(SinaWeibo.NAME);
weibo.SSOSetting(false); //设置false表示使用SSO授权方式
用了SSO授权后,有客户端的都会优先启用客户端授权,没客户端的则任然使用网页版进行授权。
当看到上面的powered by ShareSDK的时候,有些产品是需要去掉的,那么怎么办呢,答案在这里:
bbs.mob.com/thread-114-1-1.html
在使用ShareSDK三方登陆 的时候,会先判断是否已经完成授权,若已经完成授权,则会直接登陆,这时候如果用户想要切换一个账号.那么就只有清空数据了,这时候就可以用一个方法来清除用户授权信息
Platform qzone = ShareSDK.getPlatform(this, QZone.NAME);
qzone.removeAccount();
ps:
ShareSDK
的jar包,保证三方保证开放平台的登录的权限一定要审核通过ShareSDK.xml
文件,需要在三方开放平台获取appid
,和appkey
Manifest
<activity android:name="com.mob.tools.MobUIShell" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:configChanges="keyboardHidden|orientation|screenSize" android:windowSoftInputMode="stateHidden|adjustResize">
<intent-filter android:priority="1000" >
<data android:scheme="tencent1104445688" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter></activity>
<!--微信分享回调 -->
<activity android:name=".wxapi.WXEntryActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="true" android:screenOrientation="portrait" />
public class MainActivity extends AppCompatActivity implements View.OnClickListener, Handler.Callback, PlatformActionListener {
private static final int MSG_AUTH_CANCEL = 2;
private static final int MSG_AUTH_ERROR= 3;
private static final int MSG_AUTH_COMPLETE = 4;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler(this);
/**shareSDK分享*/
ShareSDK.initSDK(this);
findViewById(R.id.tvWeixin).setOnClickListener(this);
findViewById(R.id.tvWeibo).setOnClickListener(this);
findViewById(R.id.tvQq).setOnClickListener(this);
}
public void onClick(View v) {
switch(v.getId()) {
case R.id.tvWeixin: {
//微信登录
//测试时,需要打包签名;sample测试时,用项目里面的demokey.keystore
//打包签名apk,然后才能产生微信的登录
Platform wechat = ShareSDK.getPlatform(Wechat.NAME);
authorize(wechat);
} break;
case R.id.tvWeibo: {
//新浪微博
Platform sina = ShareSDK.getPlatform(SinaWeibo.NAME);
authorize(sina);
} break;
case R.id.tvQq: {
//QQ
Platform qq = ShareSDK.getPlatform(QQ.NAME);
authorize(qq);
} break;
}
}
private void authorize(Platform plat) {
if (plat == null) {
return;
}
//先移除用户授权信息,每次都可以授权,切换账号
plat.removeAccount(true);
plat.setPlatformActionListener(this);
//关闭SSO授权
plat.SSOSetting(true);
plat.showUser(null);
}
public void onComplete(Platform platform, int action, HashMap<String, Object> res) {
if (action == Platform.ACTION_USER_INFOR) {
Message msg = new Message();
msg.what = MSG_AUTH_COMPLETE;
msg.obj = new Object[] {platform, res};
handler.sendMessage(msg);
}
}
public void onError(Platform platform, int action, Throwable t) {
if (action == Platform.ACTION_USER_INFOR) {
handler.sendEmptyMessage(MSG_AUTH_ERROR);
}
t.printStackTrace();
}
public void onCancel(Platform platform, int action) {
if (action == Platform.ACTION_USER_INFOR) {
handler.sendEmptyMessage(MSG_AUTH_CANCEL);
}
}
@SuppressWarnings("unchecked")
public boolean handleMessage(Message msg) {
switch(msg.what) {
case MSG_AUTH_CANCEL: {
// 取消授权
} break;
case MSG_AUTH_ERROR: {
// 授权失败
} break;
case MSG_AUTH_COMPLETE: {
//授权成功
Object[] objs = (Object[]) msg.obj;
Platform platform = (Platform) objs[0];
HashMap<String, Object> res = (HashMap<String, Object>) objs[1];
//通过DB获取各种数据
platDB.getToken();
platDB.getUserGender();
platDB.getUserIcon();
platDB.getUserId();
platDB.getUserName();
} break;
}
return false;
}
@Override
protected void onStop() {
super.onStop();
ShareSDK.stopSDK(this);
}
}
除了使用ShareSDK之外,使用官方sdk实现三方登陆也是很不错的选择.
① QQ三方登陆
appid
和appkey
Manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application>
<activity android:name="com.tencent.tauth.AuthActivity" android:noHistory="true" android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="tencent你的AppId" />
</intent-filter>
</activity>
<activity android:name="com.tencent.connect.common.AssistActivity" android:configChanges="orientation|keyboardHidden|screenSize" />
<application>
public static Tencent mTencent;
BaseUiListener baseUiListener;
private QQToken qqToken;
private QQInfo qqInfo;
private static final int token = 0;
private static final int info = 1;
// 点击触发 注册到QQ
public void rigistQQ() {
baseUiListener = new BaseUiListener(this, token);
mTencent = Tencent.createInstance(Constants.TENCENT_APP_ID, this);
}
// 点击触发 登陆到QQ
/** * 通过这句代码,SDK实现了QQ的登录,这个方法有三个参数,第一个参数是context上下文,第二个参数SCOPO 是一个String类型的字符串,表示一些权限 * 官方文档中的说明:应用需要获得哪些API的权限,由“,”分隔。例如:SCOPE = “get_user_info,add_t”;所有权限用“all” * 第三个参数,是一个事件监听器,IUiListener接口的实例,这里用的是该接口的实现类 */
public void loginQQ() {
mTencent.login(this, "all", baseUiListener);
}
// TOKEN 相关回调
class BaseUiListener implements IUiListener {
private Context context;
private int type;
//V2.0版本,参数类型由JSONObject 改成了Object,具体类型参考api文档
public BaseUiListener(Context context, int type) {
this.context = context;
this.type = type;
}
//在这里可以做一些登录成功的处理
@Override
public void onComplete(Object o) {
JSONObject object = (JSONObject) o;
switch (type) {
case token:
qqToken = GsonUtil.jsonToBean(object.toString(), QQToken.class);
com.tencent.connect.UserInfo userInfo = new UserInfo(context, mTencent.getQQToken());
userInfo.getUserInfo(new BaseUiListener(context, info));
break;
case info:
qqInfo = GsonUtil.jsonToBean(object.toString(), QQInfo.class);
break;
}
}
//在这里可以做登录失败的处理
@Override
public void onError(UiError e) {
}
//在这里可以做登录被取消的处理
@Override
public void onCancel() {
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mTencent.onActivityResultData(requestCode, resultCode, data, baseUiListener);
super.onActivityResult(requestCode, resultCode, data);
}
②微博三方登陆.
appid
jar
包和so
文件导入工程 /** * 封装了 "access_token","expires_in","refresh_token",并提供了他们的管理功能 */
private Oauth2AccessToken mAccessToken;
private AuthInfo mAuthInfo;
/** * 注意:SsoHandler 仅当 SDK 支持 SSO 时有效 */
private SsoHandler mSsoHandler;
private void rigistWeibo(){
// 快速授权时,请不要传入 SCOPE,否则可能会授权不成功
mAuthInfo = new AuthInfo(this, Constants.WB_APP_KEY, Constants.REDIRECT_URL, Constants.SCOPE);
mSsoHandler = new SsoHandler(this, mAuthInfo);
}
private void loginWeibo(){
mSsoHandler.authorize(new AuthListener());
}
/** * 微博认证授权回调类。 1. SSO 授权时,需要在 {@link #onActivityResult} 中调用 * {@link SsoHandler#authorizeCallBack} 后, 该回调才会被执行。 2. 非 SSO * 授权时,当授权结束后,该回调就会被执行。 当授权成功后,请保存该 access_token、expires_in、uid 等信息到 * SharedPreferences 中。 */
class AuthListener implements WeiboAuthListener {
@Override
public void onComplete(Bundle values) {
// 从 Bundle 中解析 Token
mAccessToken = Oauth2AccessToken.parseAccessToken(values);
// 从这里获取用户输入的 电话号码信息
// String phoneNum = mAccessToken.getPhoneNum();
if (mAccessToken.isSessionValid()) {
// 显示 Token
// 保存 Token 到 SharedPreferences
// AccessTokenKeeper.writeAccessToken(LoginActivity.this,
// mAccessToken);
Toast.makeText(MainActivity.this, "授权成功", Toast.LENGTH_SHORT).show();
//获取用户信息
UsersAPI mUserAPI = new UsersAPI(MainActivity.this,Constants.WB_APP_KEY,mAccessToken);
long uid = Long.parseLong(mAccessToken.getUid());// 获取openid
mUserAPI.show(uid, mListener);
} else {
// 以下几种情况,您会收到 Code:
// 1. 当您未在平台上注册的应用程序的包名与签名时;
// 2. 当您注册的应用程序包名与签名不正确时;
// 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。
String code = values.getString("code");
String message = "授权失败";
if (!TextUtils.isEmpty(code)) {
message = message + "\nObtained the code: " + code;
}
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG)
.show();
}
}
@Override
public void onCancel() {
Toast.makeText(MainActivity.this, "取消授权", Toast.LENGTH_LONG)
.show();
}
@Override
public void onWeiboException(WeiboException e) {
Toast.makeText(MainActivity.this,
"Auth exception : " + e.getMessage(), Toast.LENGTH_LONG)
.show();
}
}
private RequestListener mListener = new RequestListener() {
@Override
public void onComplete(String response) {
if (!TextUtils.isEmpty(response)) {
// 调用 User#parse 将JSON串解析成User对象
User user = User.parse(response);
//.........
}
}
@Override
public void onWeiboException(WeiboException e) {
}
};
③微信三方登陆
1. 在微信官方平台创建应用,获取appid
2. 下载sdk,并导入jar包,在包名下新建一个文件夹wxapi
,在里面创建微信登陆回调类WXEntryActivity
3. 编辑Manifest
添加回调Activity
<activity android:name=".wxapi.WXEntryActivity" android:theme="@style/AppTheme.NoActionBar" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="true" android:screenOrientation="portrait" />
// 微信相关
private BaseResp resp;
public static IWXAPI api;
public WeixinTokenModel tokenModel;
private WeixinInfoModel infoModel;
// 注册到微信
private void rigistWeixin() {
api = WXAPIFactory.createWXAPI(this,Constants.APP_ID);
api.registerApp(Constants.APP_ID);
}
// 微信登陆请求
private void weiXinLogin() {
//判断微信是否安装
if (api.isWXAppInstalled() && api.isWXAppSupportAPI()) {
SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "wechat_sdk_demo_Drug A-Z";
api.sendReq(req);//第三方发送消息给微信。
} else {
UIUtil.showToastSafe("没有安装微信");
}
}
@Override
protected void onResume() {
super.onResume();
resp = Constants.baseResp;
if (null != resp && resp.getType() == ConstantsAPI.COMMAND_SENDAUTH) {
// code返回
final String weixinCode = ((SendAuth.Resp) resp).code;
if (TextUtils.isEmpty(weixinCode)) return;
ThreadManager.getShortPool().execute(new Runnable() {
@Override
public void run() {
tokenModel = WeixinLoginUtil.WXGetAccessToken(WeixinLoginUtil.getCodeRequest(weixinCode));
if (null != tokenModel && !TextUtils.isEmpty(tokenModel.access_token) && !TextUtils.isEmpty(tokenModel.openid)) {
String get_user_info_url = WeixinLoginUtil.getUserInfo(tokenModel.access_token, tokenModel.openid);
infoModel = WeixinLoginUtil.WXGetUserInfo(get_user_info_url);
}
}
});
}
Constants.baseResp = null;
}
新浪微博 sso package or sign error
完整demo:
ThirdLogin@[Github]