昨天调试了一下午终于成功 第三方QQ登录、获取个人信息,分享 QQ官方API文档写的太乱 并且很多地方没有更新 这里总结一下 方便记录和回看
实现结果图
首先进入腾讯开放平台 下载QQ的SDK 地址
[sdk下载地址]
(http://wiki.open.qq.com/wiki/mobile/SDK%E4%B8%8B%E8%BD%BD%20SDK%E4%B8%8B%E8%BD%BD)
我这里下载的是sdk v3.1.0版本
其中
登录授权返回格式
{
“ret”:0,
“pay_token”:”xxxxxxxxxxxxxxxx”,
“pf”:”openmobile_android”,
“expires_in”:”7776000”,
“openid”:”xxxxxxxxxxxxxxxxxxx”,
“pfkey”:”xxxxxxxxxxxxxxxxxxx”,
“msg”:”sucess”,
“access_token”:”xxxxxxxxxxxxxxxxxxxxx”
}
{"ret":0,"pay_token":"C0607AF4B712A8316699E9CC9AF593E8","pf":"desktop_m_qq-10000144-android-2002-","query_authority_cost":1810,"authority_cost":0,"openid":"BF0DAB7323D24A2988FCAF24533E9BC1","expires_in":7776000,"pfkey":"88d4dc02a19bbf422f511401558c80b6","msg":"","access_token":"FA4E45ECFBFB37A9A6A5BFAA19F825AE","login_cost":374}
用户信息返回格式
{
“is_yellow_year_vip”: “0”,
“ret”: 0,
“figureurl_qq_1”:
“http://q.qlogo.cn/qqapp/222222/8C75BBE3DC6B0E9A64BD31449A3C8CB0/40“,
“figureurl_qq_2”:
“http://q.qlogo.cn/qqapp/222222/8C75BBE3DC6B0E9A64BD31449A3C8CB0/100“,
“nickname”: “小罗”,
“yellow_vip_level”: “0”,
“msg”: “”,
“figureurl_1”:
“http://qzapp.qlogo.cn/qzapp/222222/8C75BBE3DC6B0E9A64BD31449A3C8CB0/50“,
“vip”: “0”,
“level”: “0”,
“figureurl_2”:
“http://qzapp.qlogo.cn/qzapp/222222/8C75BBE3DC6B0E9A64BD31449A3C8CB0/100“,
“is_yellow_vip”: “0”,
“gender”: “男”,
“figureurl”:
“http://qzapp.qlogo.cn/qzapp/222222/8C75BBE3DC6B0E9A64BD31449A3C8CB0/30”
}
{"is_yellow_year_vip":"0","ret":0,"figureurl_qq_1":"http:\/\/q.qlogo.cn\/qqapp\/222222\/BF0DAB7323D24A2988FCAF24533E9BC1\/40","figureurl_qq_2":"http:\/\/q.qlogo.cn\/qqapp\/222222\/BF0DAB7323D24A2988FCAF24533E9BC1\/100","nickname":" 心有林夕 ","yellow_vip_level":"0","is_lost":0,"msg":"","city":"安阳","figureurl_1":"http:\/\/qzapp.qlogo.cn\/qzapp\/222222\/BF0DAB7323D24A2988FCAF24533E9BC1\/50","vip":"0","level":"0","figureurl_2":"http:\/\/qzapp.qlogo.cn\/qzapp\/222222\/BF0DAB7323D24A2988FCAF24533E9BC1\/100","province":"河南","is_yellow_vip":"0","gender":"男","figureurl":"http:\/\/qzapp.qlogo.cn\/qzapp\/222222\/BF0DAB7323D24A2988FCAF24533E9BC1\/30"}
设置权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
这里是必须添加的两个写好的活动 就是在进行授权时候拉取的活动 qq已经写好
<activity
android:name="com.tencent.tauth.AuthActivity"
android:launchMode="singleTask"
android:noHistory="true" >
<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="222222" />
intent-filter>
activity>
<activity
android:name="com.tencent.connect.common.AssistActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@android:style/Theme.Translucent.NoTitleBar" >
activity>
其中 将222222替换成自己开发者认证申请的APP_ID 222222是腾讯的测试id
主界面
这里设置了三个按钮 登录,获取个人信息和分享给好友
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.qqtest.MainActivity">
<Button
android:id="@+id/btn1"
android:text="登录"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn2"
android:text="获取个人信息"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn3"
android:text="分享给好友"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/qqname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="qqname" />
<TextView
android:id="@+id/openid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="openid" />
<ImageView
android:id="@+id/qqimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
LinearLayout>
设置点击事件
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("你点击了使用qq登录按钮");
login();
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
System.out.println("开始获取用户信息");
userInfo = new UserInfo(MainActivity.this, mTencent.getQQToken());
userInfo.getUserInfo(userInfoListener);
}
});
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("你点击了使用qq分享按钮");
qqShare();
}
});
在初始数据时 继承IUiListener 重写三个不同的接口
private void initData() {
//初始化qq主操作对象
mTencent = Tencent.createInstance(APP_ID, MainActivity.this);
//要所有权限,不然会再次申请增量权限,这里不要设置成get_user_info,add_t
scope = "all";
loginListener = new IUiListener() {
@Override
public void onError(UiError arg0) {
// TODO Auto-generated method stub
}
@Override
public void onComplete(Object value) {
// TODO Auto-generated method stub
System.out.println("有数据返回..");
if (value == null) {
return;
}
try {
JSONObject jo = (JSONObject) value;
int ret = jo.getInt("ret");
System.out.println("json=" + String.valueOf(jo));
if (ret == 0) {
Toast.makeText(MainActivity.this, "登录成功",
Toast.LENGTH_LONG).show();
String openID = jo.getString("openid");
String accessToken = jo.getString("access_token");
String expires = jo.getString("expires_in");
mTencent.setOpenId(openID);
mTencent.setAccessToken(accessToken, expires);
}
} catch (Exception e) {
// TODO: handle exception
}
}
@Override
public void onCancel() {
// TODO Auto-generated method stub
}
};
userInfoListener = new IUiListener() {
@Override
public void onError(UiError arg0) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
Log.e("LoginError:", arg0.toString());
}
@Override
public void onComplete(Object arg0) {
// TODO Auto-generated method stub
if (arg0 == null) {
return;
}
try {
JSONObject jo = (JSONObject) arg0;
int ret = jo.getInt("ret");
System.out.println("json=" + String.valueOf(jo));
final String nickName = jo.getString("nickname");
final String figureurl = jo.getString("figureurl_qq_2");
String gender = jo.getString("gender");
new Thread(new Runnable() {
@Override
public void run() {
Message msg=new Message();
msg.what=0;
msg.obj=nickName;
handler.sendMessage(msg);
Message msg2=new Message();
HttpClient httpClient=new DefaultHttpClient();
HttpGet httpGet=new HttpGet(figureurl);
HttpResponse httpResponse=null;
Bitmap bitmap=null;
try {
httpResponse=httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode()==200)
{
Log.d("insw","链接成功");
byte[] data= EntityUtils.toByteArray(httpResponse.getEntity());
bitmap= BitmapFactory.decodeByteArray(data,0,data.length);
}
} catch (IOException e) {
e.printStackTrace();
}
msg2.what=1;
msg2.obj=bitmap;
handler.sendMessage(msg2);
}
}).start();
Toast.makeText(MainActivity.this, "你好," + nickName,
Toast.LENGTH_LONG).show();
} catch (Exception e) {
// TODO: handle exception
}
}
@Override
public void onCancel() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "取消登录", Toast.LENGTH_SHORT).show();
}
};
shareListener = new IUiListener() {
@Override
public void onComplete(Object o) {
//分享成功后回调
Toast.makeText(MainActivity.this, "分享成功!", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(UiError uiError) {
//分享失败后回调
}
@Override
public void onCancel() {
//取消分享后回调
}
};
}
private void login() {
//如果session无效,就开始登录
if (!mTencent.isSessionValid()) {
//开始qq授权登录
mTencent.login(MainActivity.this, scope, loginListener);
}
}
public void qqShare() {
Bundle params = new Bundle();
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
params.putString(QQShare.SHARE_TO_QQ_TITLE, "标题");
params.putString(QQShare.SHARE_TO_QQ_SUMMARY,"摘要");
params.putString(QQShare.SHARE_TO_QQ_TARGET_URL,"http://blog.csdn.net/u013451048");
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL,"http://avatar.csdn.net/C/3/D/1_u013451048.jpg");
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, "CSDN");
mTencent.shareToQQ(this, params, shareListener);
}
非常重要的一点 也是卡了很久的地方 我们需要在活动中重写onActivityResult方法 此处官方文档未更新
// 官方文档上面的是错误的
// if(requestCode == Constants.REQUEST_API) {
// if(resultCode == Constants.RESULT_LOGIN) {
// mTencent.handleLoginData(data, loginListener);
// }
// resultCode 是log出来的,官方文档里给的那个属性是没有的
正确写法如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Constants.REQUEST_LOGIN) {
if (resultCode == -1) {
Tencent.onActivityResultData(requestCode, resultCode, data, loginListener);
Tencent.handleResultData(data, loginListener);
}
}
}
在主线程中更改UI界面 设置得到的头像和昵称
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case 0:
openid.setText(msg.obj.toString());
break;
case 1:
qqimage.setImageBitmap((Bitmap) msg.obj);
break;
}
}
};
最后退出的时候注销登录
@Override
protected void onDestroy() {
if (mTencent != null) {
//注销登录
mTencent.logout(MainActivity.this);
}
super.onDestroy();
}
总结 :
1.最初一直不成功,拉取到授权页面却没有接受到回调,oncomplete方法不执行。最后发现主要问题就是要重写onActivityResult方法
2.登录成功后,要将openid设置到tencent实例中
String openID = jo.getString("openid");
String accessToken = jo.getString("access_token");
mTencent.setOpenId(openID);
mTencent.setAccessToken(accessToken, expires);
3.回调函数oncomplete的重写