第三方登录

帖子原文URL:

http://blog.csdn.net/yangyu20121224/article/details/9057257

由于公司项目的需要,要实现在项目中使用第三方授权登录以及分享文字和图片等这样的效果,几经波折,查阅了一番资料,做了一个Demo。实现起来的效果还是不错的,不敢独享,决定写一个总结的教程,供大家互相交流、学习和参考,博主只求能和大家共同进步。希望能多多支持!

这篇文章中,我们使用到了Share SDK,它是为iOS、Android、WP8的APP提供社会化功能的一个组件,目前支持如QQ、微信、新浪微博、腾讯微博、开心网、人人网、豆瓣、网易微博、搜狐微博、facebook、twitter、google+等国内外主流社交平台。


一、实现的效果图

主界面效果图 授权登录页面效果图

第三方登录_第1张图片第三方登录_第2张图片

点击分享按钮弹出分享分享界面 有界面图文分享,分享成功后会发送消息提示

第三方登录_第3张图片第三方登录_第4张图片

第三方登录_第5张图片第三方登录_第6张图片



二、项目结构目录

第三方登录_第7张图片

第三方登录_第8张图片


三、编码前的准备工作


1、获取Libs

Libs包含ShareSDK的类库,具体包括三个文件夹,分别是ShareSDK的全局依赖库、ShareSDK当前支持的所有平台工具库和ShareSDK可视化UI的一些支持库。“全局依赖库”是集成ShareSDK的基础,ShareSDK的任何平台都依赖于这个库,而“ShareSDK-GUI”提供的是一个测栏控件和一个快捷分享工具,以方便读者更快速地集成ShareSDK。Libs下载地址


2、导入Libs

<1> 将“Libs\Global-Dependences”下的jar包复制到您的libs目录下。

<2> 从“Libs\Platforms”中选择您感兴趣的平台,比方说“新浪微博”、“QQ空间”、“腾讯微博”等,复制相应的压缩包到你项目的libs目录下并解压

<3> 如果你决定使用shareSDK提供的快捷分享工具,还需要复制“Libs\ShareSDK-GUI”中复制“cn.sharesdk.onekeyshare.jar”到你的项目中。

<4> 一般来说,ADT会自动将你添加到libs目录下的jar包添加到“Android Dependencies”中。但是如果你的开发环境不能自动加载ShareSDK的jar包到你的项目中,那么只能手动添加,如下图所示:

第三方登录_第9张图片


四、详细的编码实现


1、ShareSdK使用统一的格式管理你在不同平台上注册的开发者信息。这些信息都存放在项目的“assets/ShareSDKDevInfor.xml”中,ShareSDKDevInfor.xml:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <DevInfor>
  3. <!--说明:
  4. 1、表格中的第一项
  5. <ShareSDK AppKey="api20" />
  6. 是必须的,其中的AppKey是你在Share SDK上注册的开发者帐号的AppKey

  7. 2、所有集成到你项目的平台都应该为其在表格中填写相对应的开发者信息,以新浪微博为例:
  8. <SinaWeibo
  9. SortId="此平台在分享列表中的位置,由开发者自行定义,可以是任何整型数字,数值越大越靠后"
  10. AppKey="填写你在新浪微博上注册的AppKey"
  11. AppSecret="填写你在新浪微博上注册到的AppKey"
  12. Id="自定义字段,整形,用于你项目中对此平台的识别符"
  13. RedirectUrl="填写你在新浪微博上注册的RedirectUrl"/>

  14. 各个平台注册应用信息的地址如下:
  15. 新浪微博:http://open.weibo.com
  16. 腾讯微博:http://dev.t.qq.com
  17. QQ空间:http://connect.qq.com/intro/login/
  18. 网易微博:http://open.t.163.com
  19. 搜狐微博:http://open.t.sohu.com
  20. 豆瓣:http://developers.douban.com
  21. 人人网:http://dev.renren.com
  22. 开心网:http://open.kaixin001.com
  23. Instapaper:http://www.instapaper.com/main/request_oauth_consumer_token
  24. 有道云笔记:http://note.youdao.com/open/developguide.html#app
  25. facebook:https://developers.facebook.com
  26. twitter:https://dev.twitter.com
  27. 搜狐随身看:https://open.sohu.com
  28. QQ好友分享:http://mobile.qq.com/api/
  29. 微信:http://open.weixin.qq.com-->

  30. <ShareSDK
  31. AppKey = "api20"/><!-- AppKey="104972cdd48" "23a9371d3a8"-->

  32. <SinaWeibo
  33. SortId="1"
  34. AppKey="3201194191"
  35. AppSecret="0334252914651e8f76bad63337b3b78f"
  36. Id="1"
  37. RedirectUrl="http://appgo.cn"/>

  38. <TencentWeibo
  39. SortId="2"
  40. AppKey="801307650"
  41. AppSecret="ae36f4ee3946e1cbb98d6965b0b2ff5c"
  42. RedirectUri="http://sharesdk.cn"
  43. Id="2" />

  44. <QZone
  45. SortId="3"
  46. AppId="100371282"
  47. AppKey="aed9b0303e3ed1e27bae87c33761161d"
  48. Id="3"
  49. RedirectUrl="http://www.shareSDK.cn"/>

  50. <Renren
  51. SortId="4"
  52. AppId="226427"
  53. ApiKey="fc5b8aed373c4c27a05b712acba0f8c3"
  54. Id="4"
  55. SecretKey="f29df781abdd4f49beca5a2194676ca4"/>

  56. </DevInfor>

2、配置AndroidManifest.xml,不同的集成度需要在AndroidManifest.xml中添加的内容也不一样。但是首先你需要添加下面的权限列表:

[html]  view plain copy
  1. <uses-permissionandroid:name="android.permission.INTERNET"/>
  2. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  3. <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
  4. <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"/>
  5. <uses-permissionandroid:name="android.permission.CHANGE_WIFI_STATE"/>
  6. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  7. <uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>


这些权限将允许你的项目和ShareSDK获取连接网络的权限、获取你的设备网络状态的权限、实现https安全连接的权限、读取手机设备状态的权限和保存必要配置的权限。一般来说,即便不集成ShareSDK,大部分的项目也都会注册申请这些权限。

注意:大家在加入这个"android.permission.WRITE_APN_SETTINGS"权限的时候,可能有些读者的编译器会报错,博主就遇到了这样的情况,这个是ADT Lint工具的问题。

解决的办法是:依照下面的路径“Window —> Preferences —> android—> lint error checking”打开lint的配置页面,然后去掉页面顶部的两个勾选,之后再clean项目就能处理。如下图所示:

第三方登录_第10张图片

3、其次,为了授权操作可以顺利完成,需要在application下注册下面的Activity:

[html]  view plain copy
  1. <activity
  2. android:name="cn.sharesdk.framework.AuthorizeActivity"
  3. android:configChanges="keyboardHidden|orientation"
  4. android:screenOrientation="portrait"
  5. android:theme="@android:style/Theme.Translucent.NoTitleBar"
  6. android:windowSoftInputMode="stateHidden|adjustResize">
  7. </activity>

AuthorizeActivity的路径是固定的,一定要在“cn.sharesdk.framework”下,因为他在Share-Core包中。

4、添加布局页面,首先是主界面的布局页面,activity_main.xml:

[html]  view plain copy
  1. <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">

  5. <Button
  6. android:id="@+id/btnLogin"
  7. android:layout_width="fill_parent"
  8. android:layout_height="44dp"
  9. android:layout_above="@+id/btnShareAllGui"
  10. android:layout_centerHorizontal="true"
  11. android:layout_margin="5dp"
  12. android:background="@drawable/btn_back"
  13. android:text="用户授权登录"
  14. android:textSize="16dp"/>

  15. <Button
  16. android:id="@+id/btnShareAllGui"
  17. android:layout_width="fill_parent"
  18. android:layout_height="44dp"
  19. android:layout_above="@+id/btnShareAll"
  20. android:layout_margin="5dp"
  21. android:background="@drawable/btn_back"
  22. android:text="分享全部(有分享界面)"
  23. android:textSize="16dp"/>

  24. <Button
  25. android:id="@+id/btnShareAll"
  26. android:layout_width="fill_parent"
  27. android:layout_height="44dp"
  28. android:layout_alignParentRight="true"
  29. android:layout_centerVertical="true"
  30. android:layout_margin="5dp"
  31. android:background="@drawable/btn_back"
  32. android:text="分享全部(无界面,直接分享)"
  33. android:textSize="16dp"/>

  34. <Button
  35. android:id="@+id/btnUserInfo"
  36. android:layout_width="fill_parent"
  37. android:layout_height="44dp"
  38. android:layout_below="@+id/btnShareAll"
  39. android:layout_margin="5dp"
  40. android:layout_marginTop="41dp"
  41. android:background="@drawable/btn_back"
  42. android:text="获取授权用户资料"
  43. android:textSize="16dp"/>

  44. </RelativeLayout>

5、用户授权登录的布局页面,activity_auth.xml:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:background="#fff5f5f5"
  6. android:orientation="vertical">

  7. <!--ShareSDK-Core包下封装的一个标题栏-->
  8. <cn.sharesdk.framework.TitleLayout
  9. android:id="@+id/llTitle"
  10. android:layout_width="fill_parent"
  11. android:layout_height="wrap_content"
  12. android:background="@drawable/title_back"/>

  13. <LinearLayout
  14. android:id="@+id/llBody"
  15. android:layout_width="fill_parent"
  16. android:layout_height="wrap_content"
  17. android:layout_alignParentLeft="true"
  18. android:layout_alignParentTop="true"
  19. android:layout_marginTop="58dp"
  20. android:orientation="vertical"
  21. android:padding="10dp">

  22. <LinearLayout
  23. android:layout_width="fill_parent"
  24. android:layout_height="50dp"
  25. android:background="@drawable/list_item_first_normal"
  26. android:paddingLeft="10dp"
  27. android:paddingRight="10dp">

  28. <ImageView
  29. android:layout_width="30dp"
  30. android:layout_height="30dp"
  31. android:layout_gravity="center_vertical"
  32. android:layout_marginRight="10dp"
  33. android:scaleType="centerInside"
  34. android:src="@drawable/sina_weibo"/>

  35. <CheckedTextView
  36. android:id="@+id/ctvSw"
  37. android:layout_width="fill_parent"
  38. android:layout_height="fill_parent"
  39. android:layout_gravity="center_vertical"
  40. android:drawablePadding="10dp"
  41. android:drawableRight="@drawable/cb_drw"
  42. android:gravity="center_vertical"
  43. android:singleLine="true"
  44. android:text="@string/not_yet_authorized"
  45. android:textColor="#ff000000"
  46. android:textSize="20dp"/>
  47. </LinearLayout>

  48. <LinearLayout
  49. android:layout_width="fill_parent"
  50. android:layout_height="50dp"
  51. android:background="@drawable/list_item_middle_normal"
  52. android:paddingLeft="10dp"
  53. android:paddingRight="10dp">

  54. <ImageView
  55. android:layout_width="30dp"
  56. android:layout_height="30dp"
  57. android:layout_gravity="center_vertical"
  58. android:layout_marginRight="10dp"
  59. android:scaleType="centerInside"
  60. android:src="@drawable/tencent_weibo"/>

  61. <CheckedTextView
  62. android:id="@+id/ctvTc"
  63. android:layout_width="fill_parent"
  64. android:layout_height="fill_parent"
  65. android:layout_gravity="center_vertical"
  66. android:drawablePadding="10dp"
  67. android:drawableRight="@drawable/cb_drw"
  68. android:gravity="center_vertical"
  69. android:singleLine="true"
  70. android:text="@string/not_yet_authorized"
  71. android:textColor="#ff000000"
  72. android:textSize="20dp"/>
  73. </LinearLayout>

  74. <LinearLayout
  75. android:layout_width="fill_parent"
  76. android:layout_height="50dp"
  77. android:background="@drawable/list_item_middle_normal"
  78. android:paddingLeft="10dp"
  79. android:paddingRight="10dp">

  80. <ImageView
  81. android:layout_width="30dp"
  82. android:layout_height="30dp"
  83. android:layout_gravity="center_vertical"
  84. android:layout_marginRight="10dp"
  85. android:scaleType="centerInside"
  86. android:src="@drawable/renren"/>

  87. <CheckedTextView
  88. android:id="@+id/ctvRr"
  89. android:layout_width="fill_parent"
  90. android:layout_height="fill_parent"
  91. android:layout_gravity="center_vertical"
  92. android:drawablePadding="10dp"
  93. android:drawableRight="@drawable/cb_drw"
  94. android:gravity="center_vertical"
  95. android:singleLine="true"
  96. android:text="@string/not_yet_authorized"
  97. android:textColor="#ff000000"
  98. android:textSize="20dp"/>
  99. </LinearLayout>

  100. <LinearLayout
  101. android:layout_width="fill_parent"
  102. android:layout_height="50dp"
  103. android:background="@drawable/list_item_last_normal"
  104. android:paddingLeft="10dp"
  105. android:paddingRight="10dp">

  106. <ImageView
  107. android:layout_width="30dp"
  108. android:layout_height="30dp"
  109. android:layout_gravity="center_vertical"
  110. android:layout_marginRight="10dp"
  111. android:scaleType="centerInside"
  112. android:src="@drawable/qzone"/>

  113. <CheckedTextView
  114. android:id="@+id/ctvQz"
  115. android:layout_width="fill_parent"
  116. android:layout_height="fill_parent"
  117. android:layout_gravity="center_vertical"
  118. android:drawablePadding="10dp"
  119. android:drawableRight="@drawable/cb_drw"
  120. android:gravity="center_vertical"
  121. android:singleLine="true"
  122. android:text="@string/not_yet_authorized"
  123. android:textColor="#ff000000"
  124. android:textSize="20dp"/>
  125. </LinearLayout>
  126. </LinearLayout>

  127. </RelativeLayout>


6、获得用户信息布局界面,activity_userinfo.xml:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:background="#fff5f5f5"
  6. android:orientation="vertical">

  7. <!--ShareSDK-Core包下封装的一个标题栏-->
  8. <cn.sharesdk.framework.TitleLayout
  9. android:id="@+id/llTitle"
  10. android:layout_width="fill_parent"
  11. android:layout_height="wrap_content"
  12. android:background="@drawable/title_back"/>

  13. <Button
  14. android:id="@+id/btnQz"
  15. android:layout_width="fill_parent"
  16. android:layout_height="44dp"
  17. android:layout_centerVertical="true"
  18. android:layout_margin="5dp"
  19. android:background="@drawable/btn_back"
  20. android:text="@string/get_user_info_qz"
  21. android:textSize="16dp"/>

  22. <Button
  23. android:id="@+id/btnRr"
  24. android:layout_width="fill_parent"
  25. android:layout_height="44dp"
  26. android:layout_above="@+id/btnQz"
  27. android:layout_margin="5dp"
  28. android:background="@drawable/btn_back"
  29. android:text="@string/get_user_info_rr"
  30. android:textSize="16dp"/>

  31. <Button
  32. android:id="@+id/btnSw"
  33. android:layout_width="fill_parent"
  34. android:layout_height="44dp"
  35. android:layout_above="@+id/btnRr"
  36. android:layout_margin="5dp"
  37. android:background="@drawable/btn_back"
  38. android:text="@string/get_user_info_sw"
  39. android:textSize="16dp"/>

  40. <Button
  41. android:id="@+id/btnTc"
  42. android:layout_width="fill_parent"
  43. android:layout_height="44dp"
  44. android:layout_below="@+id/btnQz"
  45. android:layout_centerHorizontal="true"
  46. android:layout_margin="5dp"
  47. android:background="@drawable/btn_back"
  48. android:text="@string/get_user_info_tc"
  49. android:textSize="16dp"/>

  50. </RelativeLayout>


7、显示用户获得的信息布局界面,activity_userinfo.xml:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:background="#fff5f5f5"
  6. android:orientation="vertical">

  7. <!--ShareSDK-Core包下封装的一个标题栏-->
  8. <cn.sharesdk.framework.TitleLayout
  9. android:id="@+id/llTitle"
  10. android:layout_width="fill_parent"
  11. android:layout_height="wrap_content"
  12. android:background="@drawable/title_back"/>

  13. <ScrollView
  14. android:layout_width="fill_parent"
  15. android:layout_height="wrap_content"
  16. android:layout_alignParentBottom="true"
  17. android:layout_below="@id/llTitle"
  18. android:paddingBottom="10dp"
  19. android:paddingLeft="10dp"
  20. android:paddingTop="10dp">

  21. <TextView
  22. android:id="@+id/tvJson"
  23. android:layout_width="fill_parent"
  24. android:layout_height="wrap_content"
  25. android:layout_marginRight="10dp"
  26. android:autoLink="all"
  27. android:background="@drawable/list_item_single_normal"
  28. android:textColor="#ff000000"/>
  29. </ScrollView>

  30. </RelativeLayout>

8、主界面入口Activity类,MainActivity.Java:

[java]  view plain copy
  1. package com.yangyu.activity;

  2. import java.io.File;
  3. import java.io.FileOutputStream;

  4. import android.app.Activity;
  5. import android.content.Intent;
  6. import android.graphics.Bitmap;
  7. import android.graphics.Bitmap.CompressFormat;
  8. import android.graphics.BitmapFactory;
  9. import android.os.Bundle;
  10. import android.os.Environment;
  11. import android.view.View;
  12. import android.view.View.OnClickListener;
  13. import android.widget.Button;
  14. import cn.sharesdk.framework.AbstractWeibo;
  15. import cn.sharesdk.onekeyshare.ShareAllGird;

  16. import com.yangyu.mysharethings.R;

  17. /**
  18. * @author yangyu
  19. * 功能描述:主Activity类,程序的入口类
  20. */
  21. public class MainActivityextends Activity implements OnClickListener {
  22. //定义图片存放的地址
  23. public static String TEST_IMAGE;

  24. //定义"账号登陆"按钮,"有分享界面按钮","无分享界面"按钮,"得到用户资料"按钮
  25. private Button authLoginBtn,shareGuiBtn,shareBtn,getInfoBtn;

  26. @Override
  27. protected void onCreate(Bundle savedInstanceState) {
  28. super.onCreate(savedInstanceState);
  29. setContentView(R.layout.activity_main);

  30. //初始化ShareSDK
  31. AbstractWeibo.initSDK(this);

  32. initImagePath();

  33. initView();

  34. initData();
  35. }

  36. /**
  37. * 初始化组件
  38. */
  39. private void initView(){
  40. authLoginBtn = (Button)findViewById(R.id.btnLogin);
  41. shareGuiBtn = (Button)findViewById(R.id.btnShareAllGui);
  42. shareBtn = (Button)findViewById(R.id.btnShareAll);
  43. getInfoBtn = (Button)findViewById(R.id.btnUserInfo);
  44. }

  45. /**
  46. * 初始化数据
  47. */
  48. private void initData(){
  49. //设置按钮监听事件
  50. authLoginBtn.setOnClickListener(this);
  51. shareGuiBtn.setOnClickListener(this);
  52. shareBtn.setOnClickListener(this);
  53. getInfoBtn.setOnClickListener(this);
  54. }

  55. /**
  56. * 初始化分享的图片
  57. */
  58. private void initImagePath() {
  59. try {//判断SD卡中是否存在此文件夹
  60. if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
  61. && Environment.getExternalStorageDirectory().exists()) {
  62. TEST_IMAGE = Environment.getExternalStorageDirectory().getAbsolutePath() +"/pic.png";
  63. }
  64. else {
  65. TEST_IMAGE = getApplication().getFilesDir().getAbsolutePath() + "/pic.png";
  66. }
  67. File file = new File(TEST_IMAGE);
  68. //判断图片是否存此文件夹中
  69. if (!file.exists()) {
  70. file.createNewFile();
  71. Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.pic);
  72. FileOutputStream fos = new FileOutputStream(file);
  73. pic.compress(CompressFormat.JPEG, 100, fos);
  74. fos.flush();
  75. fos.close();
  76. }
  77. catch(Throwable t) {
  78. t.printStackTrace();
  79. TEST_IMAGE = null;
  80. }
  81. }

  82. /**
  83. * 按钮监听事件
  84. */
  85. @Override
  86. public void onClick(View v) {
  87. switch (v.getId()) {
  88. case R.id.btnLogin:
  89. startActivity(new Intent(MainActivity.this,AuthActivity.class));
  90. break;
  91. case R.id.btnShareAllGui:
  92. showGrid(false);
  93. break;
  94. case R.id.btnShareAll:
  95. showGrid(true);
  96. break;
  97. case R.id.btnUserInfo:
  98. // 获取自己的资料
  99. Intent i = new Intent(this, GetInforActivity.class);
  100. startActivity(i);
  101. break;
  102. default:
  103. break;
  104. }

  105. }

  106. /**
  107. * 使用快捷分享完成图文分享
  108. */
  109. private void showGrid(boolean silent) {
  110. Intent i = new Intent(this, ShareAllGird.class);
  111. // 分享时Notification的图标
  112. i.putExtra("notif_icon", R.drawable.ic_launcher);
  113. // 分享时Notification的标题
  114. i.putExtra("notif_title"this.getString(R.string.app_name));

  115. // title标题,在印象笔记、邮箱、信息、微信(包括好友和朋友圈)、人人网和QQ空间使用,否则可以不提供
  116. i.putExtra("title"this.getString(R.string.share));
  117. // titleUrl是标题的网络链接,仅在人人网和QQ空间使用,否则可以不提供
  118. i.putExtra("titleUrl""http://sharesdk.cn");
  119. // text是分享文本,所有平台都需要这个字段
  120. i.putExtra("text"this.getString(R.string.share_content));
  121. // imagePath是本地的图片路径,所有平台都支持这个字段,不提供,则表示不分享图片
  122. i.putExtra("imagePath", MainActivity.TEST_IMAGE);
  123. // url仅在微信(包括好友和朋友圈)中使用,否则可以不提供
  124. i.putExtra("url""http://sharesdk.cn");
  125. // thumbPath是缩略图的本地路径,仅在微信(包括好友和朋友圈)中使用,否则可以不提供
  126. i.putExtra("thumbPath", MainActivity.TEST_IMAGE);
  127. // appPath是待分享应用程序的本地路劲,仅在微信(包括好友和朋友圈)中使用,否则可以不提供
  128. i.putExtra("appPath", MainActivity.TEST_IMAGE);
  129. // comment是我对这条分享的评论,仅在人人网和QQ空间使用,否则可以不提供
  130. i.putExtra("comment"this.getString(R.string.share));
  131. // site是分享此内容的网站名称,仅在QQ空间使用,否则可以不提供
  132. i.putExtra("site"this.getString(R.string.app_name));
  133. // siteUrl是分享此内容的网站地址,仅在QQ空间使用,否则可以不提供
  134. i.putExtra("siteUrl""http://sharesdk.cn");

  135. // 是否直接分享
  136. i.putExtra("silent", silent);
  137. this.startActivity(i);
  138. }

  139. /**
  140. * 将action转换为String
  141. */
  142. public static String actionToString(int action) {
  143. switch (action) {
  144. case AbstractWeibo.ACTION_AUTHORIZING:return "ACTION_AUTHORIZING";
  145. case AbstractWeibo.ACTION_GETTING_FRIEND_LIST: return "ACTION_GETTING_FRIEND_LIST";
  146. case AbstractWeibo.ACTION_FOLLOWING_USER:return "ACTION_FOLLOWING_USER";
  147. case AbstractWeibo.ACTION_SENDING_DIRECT_MESSAGE:return "ACTION_SENDING_DIRECT_MESSAGE";
  148. case AbstractWeibo.ACTION_TIMELINE: return "ACTION_TIMELINE";
  149. case AbstractWeibo.ACTION_USER_INFOR: return "ACTION_USER_INFOR";
  150. case AbstractWeibo.ACTION_SHARE: return "ACTION_SHARE";
  151. default: {
  152. return "UNKNOWN";
  153. }
  154. }
  155. }

  156. protected void onDestroy() {
  157. //结束ShareSDK的统计功能并释放资源
  158. AbstractWeibo.stopSDK(this);
  159. super.onDestroy();
  160. }
  161. }

集成ShareSDK需要至少在两个地方添加代码,包括:

<1> 在onCreate中插入下面的代码:

[java]  view plain copy
  1. //初始化ShareSDK
  2. AbstractWeibo.initSDK(this);

这行代码会初始化ShareSDK,此后对ShareSDK的操作都依次为基础。如果不在所有ShareSDK的操作之前调用这行代码,会抛出空指针异常。

<2> 在项目的出口Activity的onDestroy方法的第一行插入下面的代码:

[java]  view plain copy
  1. protected void onDestroy() {
  2. //结束ShareSDK的统计功能并释放资源
  3. AbstractWeibo.stopSDK(this);
  4. super.onDestroy();
  5. }

这行代码会结束ShareSDK的统计功能并释放资源。如果这行代码没有被调用,那么

“应用启动次数”的统计将不会准确,因为应用可能从来没有被关闭。

InitSDK是可以重复调用的,其实ShareSDK建议在你不确定的时候调用这个方法,

来保证ShareSDK被正确初始化。而stopSDK一旦调用了,就必须重新调用InitSDK才能使

用ShareSDK的功能,否则会出现空指针异常。

在这段代码中,还使用到了快捷分享,如下图所示,点击按钮弹出快捷分享界面:

第三方登录_第11张图片第三方登录_第12张图片


什么是快捷分享呢?快捷分享是ShareSDK提供的一套基于其接口的GUI。通过简单的配置,可以在不考虑平台的情况下,调用很少的代码,就完成分享的操作。快捷分享的jar包放在SDK解压目录的"Libs\ShareSDK-GUI"中,叫做"cn.sharesdk.oneshare.jar"。快捷分享使用了两个Activity,需要在AndroidManifest.xml中注册这两个Activity:

[html]  view plain copy
  1. <activity
  2. android:name="cn.sharesdk.onekeyshare.ShareAllGird"
  3. android:configChanges="keyboardHidden|orientation"
  4. android:screenOrientation="portrait"
  5. android:theme="@android:style/Theme.Translucent.NoTitleBar"
  6. android:windowSoftInputMode="adjustPan|stateHidden"/>
  7. <activity
  8. android:name="cn.sharesdk.onekeyshare.SharePage"
  9. android:configChanges="keyboardHidden|orientation"
  10. android:screenOrientation="portrait"
  11. android:windowSoftInputMode="stateHidden|adjustResize"/>

9、帐号授权登录界面,AuthActivity.java:

[java]  view plain copy
  1. package com.yangyu.activity;

  2. import java.util.HashMap;

  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.os.Handler;
  6. import android.os.Handler.Callback;
  7. import android.os.Message;
  8. import android.view.View;
  9. import android.view.View.OnClickListener;
  10. import android.widget.CheckedTextView;
  11. import android.widget.Toast;
  12. import cn.sharesdk.framework.AbstractWeibo;
  13. import cn.sharesdk.framework.TitleLayout;
  14. import cn.sharesdk.framework.WeiboActionListener;
  15. import cn.sharesdk.renren.Renren;
  16. import cn.sharesdk.sina.weibo.SinaWeibo;
  17. import cn.sharesdk.tencent.qzone.QZone;
  18. import cn.sharesdk.tencent.weibo.TencentWeibo;

  19. import com.yangyu.mysharethings.R;

  20. /**
  21. * @author yangyu
  22. * 功能描述:授权和取消授权Activity,由于UI显示需要授权过的平台显示账户的名称,
  23. * 因此此页面事实上展示的是“获取用户资料”和“取消授权”两个功能。
  24. */
  25. public class AuthActivityextends Activity implements Callback, OnClickListener, WeiboActionListener {
  26. //定义CheckedTextView对象
  27. private CheckedTextView sinaCt,qzoneCt,tengxunCt,renrenCt;

  28. //定义Handler对象
  29. private Handler handler;

  30. //定义标题栏对象
  31. private TitleLayout llTitle;

  32. @Override
  33. protected void onCreate(Bundle savedInstanceState) {
  34. super.onCreate(savedInstanceState);
  35. setContentView(R.layout.activity_auth);

  36. initView();

  37. initData();
  38. }

  39. /**
  40. * 初始化组件
  41. */
  42. private void initView(){
  43. //实例化Handler对象并设置信息回调监听接口
  44. handler = new Handler(this);

  45. //得到标题栏对象
  46. llTitle = (TitleLayout) findViewById(R.id.llTitle);

  47. //得到组件对象
  48. sinaCt = (CheckedTextView)findViewById(R.id.ctvSw);
  49. qzoneCt = (CheckedTextView)findViewById(R.id.ctvQz);
  50. tengxunCt = (CheckedTextView)findViewById(R.id.ctvTc);
  51. renrenCt = (CheckedTextView)findViewById(R.id.ctvRr);
  52. }

  53. /**
  54. * 初始化数据
  55. */
  56. private void initData(){
  57. llTitle.getBtnBack().setOnClickListener(new OnClickListener() {
  58. @Override
  59. public void onClick(View v) {
  60. finish();
  61. }
  62. });
  63. llTitle.getTvTitle().setText("用户授权登录");

  64. //设置监听
  65. sinaCt.setOnClickListener(this);
  66. qzoneCt.setOnClickListener(this);
  67. tengxunCt.setOnClickListener(this);
  68. renrenCt.setOnClickListener(this);

  69. //获取平台列表
  70. AbstractWeibo[] weibos = AbstractWeibo.getWeiboList(this);

  71. for(int i =0;i < weibos.length;i++){
  72. if (!weibos[i].isValid()) {
  73. continue;
  74. }

  75. CheckedTextView ctv = getView(weibos[i]);
  76. if (ctv != null) {
  77. ctv.setChecked(true);
  78. // 得到授权用户的用户名称
  79. String userName = weibos[i].getDb().get("nickname");
  80. if (userName == null || userName.length() <= 0 || "null".equals(userName)) {
  81. // 如果平台已经授权却没有拿到帐号名称,则自动获取用户资料,以获取名称
  82. userName = getWeiboName(weibos[i]);
  83. //添加平台事件监听
  84. weibos[i].setWeiboActionListener(this);
  85. //显示用户资料,null表示显示自己的资料
  86. weibos[i].showUser(null);
  87. }
  88. ctv.setText(userName);
  89. }
  90. }
  91. }

  92. /**
  93. * 在CheckedTextView组件中显示授权用户的名称
  94. */
  95. private CheckedTextView getView(AbstractWeibo weibo) {
  96. if (weibo == null) {
  97. return null;
  98. }

  99. String name = weibo.getName();
  100. if (name == null) {
  101. return null;
  102. }

  103. View v = null;
  104. if (SinaWeibo.NAME.equals(name)) {
  105. v = findViewById(R.id.ctvSw);
  106. }
  107. else if (TencentWeibo.NAME.equals(name)) {
  108. v = findViewById(R.id.ctvTc);
  109. }
  110. else if (Renren.NAME.equals(name)) {
  111. v = findViewById(R.id.ctvRr);
  112. }
  113. else if (QZone.NAME.equals(name)) {
  114. v = findViewById(R.id.ctvQz);
  115. }

  116. if (v == null) {
  117. return null;
  118. }

  119. if (! (v instanceof CheckedTextView)) {
  120. return null;
  121. }

  122. return (CheckedTextView) v;
  123. }

  124. /**
  125. * 得到授权用户的用户名称
  126. */
  127. private String getWeiboName(AbstractWeibo weibo) {
  128. if (weibo == null) {
  129. return null;
  130. }

  131. String name = weibo.getName();
  132. if (name == null) {
  133. return null;
  134. }

  135. int res = 0;
  136. if (SinaWeibo.NAME.equals(name)) {
  137. res = R.string.sinaweibo;
  138. }
  139. else if (TencentWeibo.NAME.equals(name)) {
  140. res = R.string.tencentweibo;
  141. }
  142. else if (Renren.NAME.equals(name)) {
  143. res = R.string.renren;
  144. }
  145. else if (QZone.NAME.equals(name)) {
  146. res = R.string.qzone;
  147. }

  148. if (res == 0) {
  149. return name;
  150. }
  151. return this.getResources().getString(res);
  152. }

  153. /**
  154. * 授权和取消授权的按钮点击监听事件
  155. */
  156. @Override
  157. public void onClick(View v) {
  158. AbstractWeibo weibo = getWeibo(v.getId());

  159. CheckedTextView ctv = (CheckedTextView) v;
  160. if (weibo == null) {
  161. ctv.setChecked(false);
  162. ctv.setText(R.string.not_yet_authorized);
  163. return;
  164. }

  165. if (weibo.isValid()) {
  166. weibo.removeAccount();
  167. ctv.setChecked(false);
  168. ctv.setText(R.string.not_yet_authorized);
  169. return;
  170. }

  171. weibo.setWeiboActionListener(this);
  172. weibo.showUser(null);
  173. }

  174. /**
  175. * 获得授权
  176. */
  177. private AbstractWeibo getWeibo(int vid) {
  178. String name = null;
  179. switch (vid) {
  180. // 进入新浪微博的授权页面
  181. case R.id.ctvSw:
  182. name = SinaWeibo.NAME;
  183. break;
  184. // 进入腾讯微博的授权页面
  185. case R.id.ctvTc:
  186. name = TencentWeibo.NAME;
  187. break;
  188. // 进入人人网的授权页面
  189. case R.id.ctvRr:
  190. name = Renren.NAME;
  191. break;
  192. // 进入QQ空间的授权页面
  193. case R.id.ctvQz:
  194. name = QZone.NAME;
  195. break;
  196. }

  197. if (name != null) {
  198. return AbstractWeibo.getWeibo(this, name);
  199. }
  200. return null;
  201. }

  202. /**
  203. * 授权成功的回调
  204. * weibo - 回调的平台
  205. * action - 操作的类型
  206. * res - 请求的数据通过res返回
  207. */
  208. @Override
  209. public void onComplete(AbstractWeibo weibo,int action,HashMap<String, Object> res) {
  210. Message msg = new Message();
  211. msg.arg1 = 1;
  212. msg.arg2 = action;
  213. msg.obj = weibo;
  214. handler.sendMessage(msg);
  215. }

  216. /**
  217. * 授权失败的回调
  218. */
  219. @Override
  220. public void onError(AbstractWeibo weibo,int action, Throwable t) {
  221. t.printStackTrace();

  222. Message msg = new Message();
  223. msg.arg1 = 2;
  224. msg.arg2 = action;
  225. msg.obj = weibo;
  226. handler.sendMessage(msg);
  227. }

  228. /**
  229. * 取消授权的回调
  230. */
  231. @Override
  232. public void onCancel(AbstractWeibo weibo,int action) {
  233. Message msg = new Message();
  234. msg.arg1 = 3;
  235. msg.arg2 = action;
  236. msg.obj = weibo;
  237. handler.sendMessage(msg);
  238. }

  239. /**
  240. * 处理从授权页面返回的结果
  241. *
  242. * 如果获取到用户的名称,则显示名称;否则如果已经授权,则显示平台名称
  243. */
  244. @Override
  245. public boolean handleMessage(Message msg) {
  246. AbstractWeibo weibo = (AbstractWeibo) msg.obj;
  247. String text = MainActivity.actionToString(msg.arg2);

  248. switch (msg.arg1) {
  249. case 1: { // 成功
  250. text = weibo.getName() + " completed at " + text;
  251. Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
  252. }
  253. break;
  254. case 2: {// 失败
  255. text = weibo.getName() + " caught error at " + text;
  256. Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
  257. return false;
  258. }
  259. case 3: { // 取消
  260. text = weibo.getName() + " canceled at " + text;
  261. Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
  262. return false;
  263. }
  264. }

  265. CheckedTextView ctv = getView(weibo);
  266. if (ctv != null) {
  267. ctv.setChecked(true);
  268. String userName = weibo.getDb().get("nickname"); // getAuthedUserName();
  269. if (userName == null || userName.length() <= 0
  270. || "null".equals(userName)) {
  271. userName = getWeiboName(weibo);
  272. }
  273. ctv.setText(userName);
  274. }
  275. return false;
  276. }
  277. }

10、获取用户信息界面,GetInfoActivity.java:

[java]  view plain copy
  1. package com.yangyu.activity;

  2. import java.util.HashMap;

  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. import android.os.Handler;
  7. import android.os.Handler.Callback;
  8. import android.os.Message;
  9. import android.view.View;
  10. import android.view.View.OnClickListener;
  11. import android.widget.Button;
  12. import android.widget.Toast;
  13. import cn.sharesdk.framework.AbstractWeibo;
  14. import cn.sharesdk.framework.TitleLayout;
  15. import cn.sharesdk.framework.WeiboActionListener;
  16. import cn.sharesdk.renren.Renren;
  17. import cn.sharesdk.sina.weibo.SinaWeibo;
  18. import cn.sharesdk.tencent.qzone.QZone;
  19. import cn.sharesdk.tencent.weibo.TencentWeibo;

  20. import com.yangyu.mysharethings.R;

  21. /**
  22. * @author yangyu
  23. * 功能描述:获取用户资料
  24. *
  25. * 启动页面时传递一个int类型的字段type,用于标记获取自己的资料(type = 0)还是别人的资料(type = 1)。
  26. * 如果尝试获取别人的资料,示例代码会获取不同平台Share SDK的官方帐号的资料。
  27. *
  28. * 如果资料获取成功,会通过{@link ShowInforPage}展示
  29. */
  30. public class GetInforActivityextends Activity implements Callback, OnClickListener, WeiboActionListener {

  31. //定义标题栏布局对象
  32. private TitleLayout llTitle;

  33. private Button sinaBt,renrenBt,qzoneBt,tengxunBt;

  34. private Handler handler;

  35. protected void onCreate(Bundle savedInstanceState) {
  36. super.onCreate(savedInstanceState);

  37. handler = new Handler(this);

  38. setContentView(R.layout.activity_userinfo);

  39. initView();

  40. initData();

  41. }

  42. /**
  43. * 初始化组件
  44. */
  45. private void initView(){
  46. //得到标题栏对象
  47. llTitle = (TitleLayout) findViewById(R.id.llTitle);

  48. //得到按钮对象
  49. sinaBt = (Button) findViewById(R.id.btnSw);
  50. renrenBt = (Button) findViewById(R.id.btnRr);
  51. qzoneBt = (Button) findViewById(R.id.btnQz);
  52. tengxunBt = (Button) findViewById(R.id.btnTc);


  53. }

  54. /**
  55. * 初始化数据
  56. */
  57. private void initData(){
  58. //标题栏设置返回按钮监听
  59. llTitle.getBtnBack().setOnClickListener(this);
  60. //设置标题栏的标题文本
  61. llTitle.getTvTitle().setText(R.string.get_my_info);

  62. //设置监听
  63. sinaBt.setOnClickListener(this);
  64. renrenBt.setOnClickListener(this);
  65. qzoneBt.setOnClickListener(this);
  66. tengxunBt.setOnClickListener(this);
  67. }

  68. /**
  69. * 点击按钮获取授权用户的资料
  70. */
  71. @Override
  72. public void onClick(View v) {
  73. if (v.equals(llTitle.getBtnBack())) {
  74. finish();
  75. return;
  76. }

  77. String name = null;

  78. switch (v.getId()) {
  79. case R.id.btnSw:
  80. name = SinaWeibo.NAME;
  81. break;
  82. case R.id.btnTc:
  83. name = TencentWeibo.NAME;
  84. break;
  85. case R.id.btnRr:
  86. name = Renren.NAME;
  87. break;
  88. case R.id.btnQz:
  89. name = QZone.NAME;
  90. break;
  91. }

  92. if (name != null) {
  93. AbstractWeibo weibo = AbstractWeibo.getWeibo(this, name);
  94. weibo.setWeiboActionListener(this);
  95. String account = null;

  96. weibo.showUser(account);
  97. }
  98. }

  99. public void onComplete(AbstractWeibo weibo,int action,HashMap<String, Object> res) {
  100. Message msg = new Message();
  101. msg.arg1 = 1;
  102. msg.arg2 = action;
  103. msg.obj = weibo;
  104. handler.sendMessage(msg);

  105. Message msg2 = new Message();
  106. msg2.what = 1;
  107. JsonUtils ju = new JsonUtils();
  108. String json = ju.fromHashMap(res);
  109. msg2.obj = ju.format(json);
  110. handler.sendMessage(msg2);
  111. }

  112. public void onError(AbstractWeibo weibo,int action, Throwable t) {
  113. t.printStackTrace();

  114. Message msg = new Message();
  115. msg.arg1 = 2;
  116. msg.arg2 = action;
  117. msg.obj = weibo;
  118. handler.sendMessage(msg);
  119. }

  120. public void onCancel(AbstractWeibo weibo,int action) {
  121. Message msg = new Message();
  122. msg.arg1 = 3;
  123. msg.arg2 = action;
  124. msg.obj = weibo;
  125. handler.sendMessage(msg);
  126. }

  127. /** 处理操作结果 */
  128. public boolean handleMessage(Message msg) {
  129. switch(msg.what) {
  130. case 1: {
  131. Intent i = new Intent(this, ShowInforActivity.class);
  132. i.putExtra("data", String.valueOf(msg.obj));
  133. startActivity(i);
  134. }
  135. break;
  136. default: {
  137. AbstractWeibo weibo = (AbstractWeibo) msg.obj;
  138. String text = MainActivity.actionToString(msg.arg2);
  139. switch (msg.arg1) {
  140. case 1: { // 成功
  141. text = weibo.getName() + " completed at " + text;
  142. }
  143. break;
  144. case 2: { // 失败
  145. text = weibo.getName() + " caught error at " + text;
  146. }
  147. break;
  148. case 3: { // 取消
  149. text = weibo.getName() + " canceled at " + text;
  150. }
  151. break;
  152. }

  153. Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
  154. }
  155. break;
  156. }
  157. return false;
  158. }


  159. }

11、显示用户信息界面,ShowInfoActivity.java:

[java]  view plain copy
  1. package com.yangyu.activity;

  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.view.View.OnClickListener;
  6. import android.widget.TextView;
  7. import cn.sharesdk.framework.TitleLayout;

  8. import com.yangyu.mysharethings.R;

  9. /**
  10. * @author yangyu
  11. * 功能描述:显示用户信息资料
  12. */
  13. public class ShowInforActivityextends Activity implements OnClickListener {
  14. private TitleLayout llTitle;

  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_show_userinfo);

  18. llTitle = (TitleLayout) findViewById(R.id.llTitle);
  19. llTitle.getBtnBack().setOnClickListener(this);
  20. llTitle.getTvTitle().setText("用户资料");

  21. TextView tvJson = (TextView) findViewById(R.id.tvJson);
  22. tvJson.setText(getIntent().getStringExtra("data"));
  23. }

  24. @Override
  25. public void onClick(View v) {
  26. if (v.equals(llTitle.getBtnBack())) {
  27. finish();
  28. }
  29. }

  30. }

12、这里还定义了一个Json解析类去读取授权用户的信息,JsonUtils.java:

[java]  view plain copy
  1. package com.yangyu.activity;

  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.Iterator;
  5. import java.util.Map.Entry;
  6. import org.json.JSONArray;
  7. import org.json.JSONException;
  8. import org.json.JSONObject;

  9. /**
  10. * @author yangyu
  11. * 功能描述:这是一个简易的Json-HashMap转换工具,可以将普通的json数据(字符串)
  12. * 转换为一个HashMap<Srting, Object>表格,也可以反过来操作。此外还支
  13. * 持将json数据格式化。
  14. */
  15. public class JsonUtils {

  16. /**
  17. * 将指定的json数据转成 HashMap<String, Object>对象
  18. */
  19. public HashMap<String, Object> fromJson(String jsonStr) {
  20. try {
  21. if (jsonStr.startsWith("[")
  22. && jsonStr.endsWith("]")) {
  23. jsonStr = "{\"fakelist\":" + jsonStr + "}";
  24. }

  25. JSONObject json = new JSONObject(jsonStr);
  26. return fromJson(json);
  27. catch (Throwable t) {
  28. t.printStackTrace();
  29. }
  30. return new HashMap<String, Object>();
  31. }

  32. private HashMap<String, Object> fromJson(JSONObject json)throws JSONException {
  33. HashMap<String, Object> map = new HashMap<String, Object>();
  34. @SuppressWarnings("unchecked")
  35. Iterator<String> iKey = json.keys();
  36. while(iKey.hasNext()) {
  37. String key = iKey.next();
  38. Object value = json.opt(key);
  39. if (JSONObject.NULL.equals(value)) {
  40. value = null;
  41. }
  42. if (value != null) {
  43. if (value instanceof JSONObject) {
  44. value = fromJson((JSONObject)value);
  45. }
  46. else if (valueinstanceof JSONArray) {
  47. value = fromJson((JSONArray)value);
  48. }
  49. map.put(key, value);
  50. }
  51. }
  52. return map;
  53. }

  54. private ArrayList<Object> fromJson(JSONArray array)
  55. throws JSONException {
  56. ArrayList<Object> list = new ArrayList<Object>();
  57. for (int i =0, size = array.length(); i < size; i++) {
  58. Object value = array.opt(i);
  59. if (value instanceof JSONObject) {
  60. value = fromJson((JSONObject)value);
  61. }
  62. else if (value instanceof JSONArray) {
  63. value = fromJson((JSONArray)value);
  64. }
  65. list.add(value);
  66. }
  67. return list;
  68. }

  69. /**
  70. * 将指定的HashMap<String, Object>对象转成json数据
  71. */
  72. public String fromHashMap(HashMap<String, Object> map) {
  73. try {
  74. return getJSONObject(map).toString();
  75. catch (Throwable t) {
  76. t.printStackTrace();
  77. }
  78. return "";
  79. }

  80. @SuppressWarnings("unchecked")
  81. private JSONObject getJSONObject(HashMap<String, Object> map)
  82. throws JSONException {
  83. JSONObject json = new JSONObject();
  84. for (Entry<String, Object> entry : map.entrySet()) {
  85. Object value = entry.getValue();
  86. if (value instanceof HashMap<?, ?>) {
  87. value = getJSONObject((HashMap<String, Object>)value);
  88. }
  89. else if (valueinstanceof ArrayList<?>) {
  90. value = getJSONArray((ArrayList<Object>)value);
  91. }
  92. json.put(entry.getKey(), value);
  93. }
  94. return json;
  95. }

  96. @SuppressWarnings("unchecked")
  97. private JSONArray getJSONArray(ArrayList<Object> list)
  98. throws JSONException {
  99. JSONArray array = new JSONArray();
  100. for (Object value : list) {
  101. if (value instanceof HashMap<?, ?>) {
  102. value = getJSONObject((HashMap<String, Object>)value);
  103. }
  104. else if (valueinstanceof ArrayList<?>) {
  105. value = getJSONArray((ArrayList<Object>)value);
  106. }
  107. array.put(value);
  108. }
  109. return array;
  110. }

  111. /**
  112. * 格式化一个json串
  113. */
  114. public String format(String jsonStr) {
  115. try {
  116. return format("", fromJson(jsonStr));
  117. catch (Throwable t) {
  118. t.printStackTrace();
  119. }
  120. return "";
  121. }

  122. @SuppressWarnings("unchecked")
  123. private String format(String sepStr, HashMap<String, Object> map) {
  124. StringBuffer sb = new StringBuffer();
  125. sb.append("{\n");
  126. String mySepStr = sepStr + "\t";
  127. int i = 0;
  128. for (Entry<String, Object> entry : map.entrySet()) {
  129. if (i > 0) {
  130. sb.append(",\n");
  131. }
  132. sb.append(mySepStr).append('\"').append(entry.getKey()).append("\":");
  133. Object value = entry.getValue();
  134. if (value instanceof HashMap<?, ?>) {
  135. sb.append(format(mySepStr, (HashMap<String, Object>)value));
  136. }
  137. else if (value instanceof ArrayList<?>) {
  138. sb.append(format(mySepStr, (ArrayList<Object>)value));
  139. }
  140. else if (valueinstanceof String) {
  141. sb.append('\"').append(value).append('\"');
  142. }
  143. else {
  144. sb.append(value);
  145. }
  146. i++;
  147. }
  148. sb.append('\n').append(sepStr).append('}');
  149. return sb.toString();
  150. }

  151. @SuppressWarnings("unchecked")
  152. private String format(String sepStr, ArrayList<Object> list) {
  153. StringBuffer sb = new StringBuffer();
  154. sb.append("[\n");
  155. String mySepStr = sepStr + "\t";
  156. int i = 0;
  157. for (Object value : list) {
  158. if (i > 0) {
  159. sb.append(",\n");
  160. }
  161. sb.append(mySepStr);
  162. if (value instanceof HashMap<?, ?>) {
  163. sb.append(format(mySepStr, (HashMap<String, Object>)value));
  164. }
  165. else if (valueinstanceof ArrayList<?>) {
  166. sb.append(format(mySepStr, (ArrayList<Object>)value));
  167. }
  168. else if (value instanceof String) {
  169. sb.append('\"').append(value).append('\"');
  170. }
  171. else {
  172. sb.append(value);
  173. }
  174. i++;
  175. }
  176. sb.append('\n').append(sepStr).append(']');
  177. return sb.toString();
  178. }

  179. }


讲到这里关于这一篇的内容就差不多已经讲完了,下一篇是关于微信开放平台的授权以及分享,因为微信平台不同于其它第三方平台,实现起来稍微复杂一点,所以博主打算在下一篇的文章中详细讲解。这个下一篇文章估计要等到三天后了吧,博主和女友早就商量好趁着三天小长假出去散散心了,在这里祝大家端午节快乐!博主将会长期坚持更新关于Android、Java、Cocos2d-x、Unity3d等各个不同知识领域的实例讲解和开发!希望大家继续支持!

----------------------------------------------------------------

最近弄了下QQ微信微博的登录分享,在这里做一下总结,以下登录分享使用的都是官方的最新SDk。

首先是QQ的登录:

1.第一步肯定是先去开放平台注册应用,这里步骤就不详细说了 http://open.qq.com/

2.将下载好的jar包导入工程,在AndroidManifest文件里面注册SDK里面提供的Activity

<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="tencent自己的AppId" />
    </intent-filter>
</activity>

<activity
    android:name="com.tencent.connect.common.AssistActivity"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:theme="@android:style/Theme.Translucent.NoTitleBar" />
到这里前期的准备工作就全部做好了

3.首先写一个类实现IUiListener接口作为登录后的回调

public class BaseUiListener implements IUiListener {
    @Override
    public void onComplete(Object o) {
        Toast.makeText(MyFragmentActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onError(UiError uiError) {
        Toast.makeText(MyFragmentActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onCancel() {
        Toast.makeText(MyFragmentActivity.this, "取消登录", Toast.LENGTH_SHORT).show();
    }
}
4.接下来开始写登录代码了

private Tencent mTencent;

mTencent = Tencent.createInstance("AppId", this);
if (!mTencent.isSessionValid()) {
    mTencent.login(this, "all", myFragmentActivity.baseUiListener);
}
里面的all代表你需要获取的权限

5.重写onActivityResult方法

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Constants.ACTIVITY_OK) {
        if (requestCode == Constants.REQUEST_LOGIN) {
            if (baseUiListener != null)
                Tencent.onActivityResultData(requestCode, resultCode, data, baseUiListener);
        } else if (requestCode == Constants.REQUEST_OLD_SHARE) {
            if (shareListener != null)
                Tencent.onActivityResultData(requestCode, resultCode, data, shareListener);
        } 
    }
}
里面包括了分享的回调,登录到这就全部做好了,但是一般登录后都需要获取用户信息,只需要将以下代码放在登录成功的回调里面就可以了

if (setDataListener != null) {
    try {
        JSONObject data = (JSONObject) o;
        String openID = data.getString("openid");
        String accessToken = data.getString("access_token");
        String expires = data.getString("expires_in");
        mTencent.setOpenId(openID);
        mTencent.setAccessToken(accessToken, expires);
        UserInfo userInfo = new UserInfo(getActivity(), mTencent.getQQToken());
        userInfo.getUserInfo(iUiListener);
    } catch (JSONException e) {
        e.printStackTrace();
    }
}
里面的iUiListener是获取用户信息的回调

private IUiListener iUiListener = new IUiListener() {
    @Override
    public void onComplete(Object o) {
        if (o != null) {
            Toast.makeText(getActivity(), o.toString(), Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(getActivity(), "获取信息为空", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onError(UiError uiError) {
        Toast.makeText(getActivity(), "获取信息失败", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onCancel() {

    }
};

QQ分享

QQ的分享比较简单,直接贴代码

private void share() {
        Bundle bundle = new Bundle();
//这条分享消息被好友点击后的跳转URL。
        bundle.putString(QQShare.SHARE_TO_QQ_TARGET_URL, "http://connect.qq.com/");
//分享的标题。注:PARAM_TITLE、PARAM_IMAGE_URL、PARAM_   SUMMARY不能全为空,最少必须有一个是有值的。
        bundle.putString(QQShare.SHARE_TO_QQ_TITLE, "我在测试");
//分享的图片URL
        bundle.putString(QQShare.SHARE_TO_QQ_IMAGE_URL,
                "http://img3.cache.netease.com/photo/0005/2013-03-07/8PBKS8G400BV0005.jpg");
//分享的消息摘要,最长50个字
        bundle.putString(QQShare.SHARE_TO_QQ_SUMMARY, "测试");

        mTencent.shareToQQ(this, bundle,new ShareListener());
    }
public class ShareListener implements IUiListener {
    @Override
    public void onComplete(Object o) {
        Toast.makeText(MyFragmentActivity.this, "分享成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onError(UiError uiError) {
        Toast.makeText(MyFragmentActivity.this, "分享失败", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onCancel() {
        Toast.makeText(MyFragmentActivity.this, "取消分享", Toast.LENGTH_SHORT).show();
    }
}
微信登录

由于微信的回调有所不同,所以这里登录分享一起弄,还有微信的登录分享都只能在安装了微信客户端的情况下才能使用

1.第一步同样去注册应用信息 https://open.weixin.qq.com/

2.下载SDk导入工程

3.在你的包名相应目录下新建一个wxapi目录,并在该wxapi目录下新增一个WXEntryActivity类,该类继承自Activity并实现IWXAPIEventHandler接口

第三方登录_第13张图片

4.注册这个Activity

<activity
    android:name=".wxapi.WXEntryActivity"
    android:exported="true" />

准备工作到这里也就全部做完了

5.接下来贴登录代码

private IWXAPI iwxapi;
iwxapi = WXAPIFactory.createWXAPI(this, "AppId");
if (!iwxapi.isWXAppInstalled()) {
    Toast.makeText(getActivity(), "请先安装微信应用", Toast.LENGTH_SHORT).show();
    break;
}
iwxapi.registerApp("");
SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";//需要的权限范围
req.state = "wechat_sdk_demo_test";
iwxapi.sendReq(req);

6.接下来贴上分享代码

private void weixShare() {
    WXWebpageObject wxWebpageObject = new WXWebpageObject();
    wxWebpageObject.webpageUrl = "https://www.baidu.com/";

    WXMediaMessage message = new WXMediaMessage(wxWebpageObject);
    message.title = "百度哦";
    message.description = "这是百度";
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.a);
    message.setThumbImage(bitmap);

    SendMessageToWX.Req req = new SendMessageToWX.Req();
    req.transaction = buildTransaction("webpage");
    req.message = message;
    //发送到聊天界面WXSceneSession 发送到朋友圈WXSceneTimeline
    req.scene = SendMessageToWX.Req.WXSceneSession;
    iwxapi.sendReq(req);
}
7.接下来就是在WXEntryActivity类里面处理的回调,先直接把代码全部贴出

public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
    private IWXAPI api;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // handleIntent(intent);
        api= WXAPIFactory.createWXAPI(this, "AppId");
        api.handleIntent(getIntent(), this);
    }

    @Override
    public void onReq(BaseReq baseReq) {

    }

    @Override
    public void onResp(BaseResp baseResp) {
        String result = "";
        int type = baseResp.getType();
        String typeString = "";
        //type=1表示登录,type=2表示分享
        if (type==1){
            typeString = "登录";

            if (baseResp.errCode == BaseResp.ErrCode.ERR_OK) {
                //用户同意
                String code = ((SendAuth.Resp) baseResp).code;
                Intent goMain = new Intent(this, MyFragmentActivity.class);
                goMain.putExtra("code", code);
                startActivity(goMain);
            }
        }else if (type==2){
            typeString = "分享";
        }
        switch (baseResp.errCode) {
            case BaseResp.ErrCode.ERR_OK:
                Log.i("onResp", "调用了WXEntryActivity中的onResp方法");
                result = typeString+"成功";
                break;
            case BaseResp.ErrCode.ERR_USER_CANCEL:
                result = typeString+"分享";
                break;
            case BaseResp.ErrCode.ERR_AUTH_DENIED:
                result = typeString+"被服务器拒绝";
                break;
            default:
                result = "未知操作";
                break;
        }
        Toast.makeText(this, result, Toast.LENGTH_LONG).show();
        this.finish();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
       // handleIntent(intent);
        api.handleIntent(intent, this);
    }

    private void handleIntent(Intent intent) {
        SendAuth.Resp resp = new SendAuth.Resp(intent.getExtras());
        if (resp.errCode == BaseResp.ErrCode.ERR_OK) {
            //用户同意
            String code = resp.code;
            Intent goMain = new Intent(this, MyFragmentActivity.class);
            intent.putExtra("code", code);
            startActivity(goMain);
        }
    }
}
这里我一开始使用的是自己写的hanleIntent方法绑定回调,结果发现无法区分产生的回调是登录的回调还是分享的回调,得到的type都是1,所以用了另一种方法。

微信的登录分享到这里就全部解决了


微博

登录

1.首先也一样去注册应用 http://open.weibo.com/

2.因为我现在使用的是studio开发,所以导入jar包的方式有点不同

首先我将

第三方登录_第14张图片

做为model导入工程

然后

第三方登录_第15张图片

第三方登录_第16张图片

就这样导入工程,直接导入jar包也是一样的

studio还需要在工程的main目录下创建一个jniLibs文件放置微博的so文件

第三方登录_第17张图片

到这准备工作完成

3.贴上登录代码

AuthInfo authInfo = new AuthInfo(getActivity(), WeiBoConstants.APP_KEY, WeiBoConstants.REDIRECT_URL, WeiBoConstants.SCOPE);
SsoHandler mSsoHandler = new SsoHandler(getActivity(), authInfo);
mSsoHandler.authorize(new AuthListener());
class AuthListener implements WeiboAuthListener {

    @Override
    public void onComplete(Bundle bundle) {
        Toast.makeText(getActivity(), "登录成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onWeiboException(WeiboException e) {
        Toast.makeText(getActivity(), "登录失败", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onCancel() {
        Toast.makeText(getActivity(), "取消登录", Toast.LENGTH_SHORT).show();
    }
}
这个也需要重写onActivityResult方法

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Constants.ACTIVITY_OK) {
        if (requestCode == Constants.REQUEST_LOGIN) {
            if (baseUiListener != null)
                Tencent.onActivityResultData(requestCode, resultCode, data, baseUiListener);
        } else if (requestCode == Constants.REQUEST_OLD_SHARE) {
            if (shareListener != null)
                Tencent.onActivityResultData(requestCode, resultCode, data, shareListener);
        } else {
            if (requestCode == 32973)//这个是微博的requestCode值,不知道为什么没有把它暴露出来
                if (mSsoHandler != null) {
                    mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
                }
        }
    }
}
登录到这里就做好了,接下来是分享

分享需要在你接收分享回调信息的Activity中加上

<intent-filter>

     <action Android:name="com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY" />

     <category android:name="android.intent.category.DEFAULT" />

</intent-filter>

例如

<activity android:name=".WeiBoShareActivity" >
    <intent-filter>
        <action android:name="com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

接下来贴上分享的代码

private IWeiboShareAPI mWeiboShareAPI;


mWeiboShareAPI = WeiboShareSDK.createWeiboAPI(this, WeiBoConstants.APP_KEY);

//下面这端代码需要放在onCreate里面
if (savedInstanceState != null) {
    mWeiboShareAPI.handleWeiboResponse(getIntent(), this);
}
private void weiBoShare() {

    mWeiboShareAPI.registerApp();
    ImageObject imageObject = new ImageObject();
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
    imageObject.setImageObject(bitmap);
    TextObject textObject = new TextObject();
    textObject.text = "https://www.baidu.com/";
    WeiboMultiMessage weiboMessage = new WeiboMultiMessage();
    weiboMessage.textObject =textObject;
    //  weiboMessage.mediaObject = imageObject;
    SendMultiMessageToWeiboRequest request = new SendMultiMessageToWeiboRequest();
    request.transaction = String.valueOf(System.currentTimeMillis());
    request.multiMessage = weiboMessage;
    mWeiboShareAPI.sendRequest(this,request);
}
需要重写onNewIntent方法

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    mWeiboShareAPI.handleWeiboResponse(intent, this);
}
进行分享的Activity实现IWeiboHandler.Response接口

@Override
public void onResponse(BaseResponse baseResponse) {
    switch (baseResponse.errCode) {
        case WBConstants.ErrorCode.ERR_OK:
            Toast.makeText(this, "分享成功", Toast.LENGTH_SHORT).show();
            break;
        case WBConstants.ErrorCode.ERR_CANCEL:
            Toast.makeText(this, "取消分享", Toast.LENGTH_SHORT).show();
            break;
        case WBConstants.ErrorCode.ERR_FAIL:
            Toast.makeText(this, "分享失败", Toast.LENGTH_SHORT).show();
            break;
    }
}

到这里微博分享也就全部搞好了

需要注意的是

public static final String REDIRECT_URL = "http://www.sina.com";
设置的回调页要在

第三方登录_第18张图片

写上,要不让会出现网络错误的情况


你可能感兴趣的:(第三方登录)