转:Android实现第三方授权登录,分享以及获取用户资料
Posted killer_xc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转:Android实现第三方授权登录,分享以及获取用户资料相关的知识,希望对你有一定的参考价值。
由于公司项目的需要,要实现在项目中使用第三方授权登录以及分享文字和图片等这样的效果,几经波折,查阅了一番资料,做了一个Demo。实现起来的效果还是不错的,不敢独享,决定写一个总结的教程,供大家互相交流、学习和参考,只求能和大家共同进步。希望能多多支持!
这篇文章中,我们使用到了Share SDK,它是为ios、android、WP8的APP提供社会化功能的一个组件,目前支持如QQ、微信、新浪微博、腾讯微博、开心网、人人网、豆瓣、网易微博、搜狐微博、facebook、twitter、google+等国内外主流社交平台。
一、实现的效果图
主界面效果图
授权登录页面效果图
点击分享按钮弹出分享分享界面
有界面图文分享,分享成功后会发送消息提示
二、项目结构目录
三、编码前的准备工作
1、获取Libs
Libs包含ShareSDK的类库,具体包括三个文件夹,分别是ShareSDK的全局依赖库、ShareSDK当前支持的所有平台工具库和ShareSDK可视化UI的一些支持库。“全局依赖库”是集成ShareSDK的基础,ShareSDK的任何平台都依赖于这个库,而“ShareSDK-GUI”提供的是一个测栏控件和一个快捷分享工具,以方便读者更快速地集成ShareSDK。
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包到你的项目中,那么只能手动添加,如下图所示:
四、详细的编码实现
1、ShareSdK使用统一的格式管理你在不同平台上注册的开发者信息。这些信息都存放在项目的
“assets/ShareSDKDevInfor.xml”中,ShareSDKDevInfor.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <DevInfor> 3 <!--说明: 4 1、表格中的第一项 5 <ShareSDK AppKey="api20" /> 6 是必须的,其中的AppKey是你在Share SDK上注册的开发者帐号的AppKey 7 8 2、所有集成到你项目的平台都应该为其在表格中填写相对应的开发者信息,以新浪微博为例: 9 <SinaWeibo 10 SortId="此平台在分享列表中的位置,由开发者自行定义,可以是任何整型数字,数值越大越靠后" 11 AppKey="填写你在新浪微博上注册的AppKey" 12 AppSecret="填写你在新浪微博上注册到的AppKey" 13 Id="自定义字段,整形,用于你项目中对此平台的识别符" 14 RedirectUrl="填写你在新浪微博上注册的RedirectUrl" /> 15 16 各个平台注册应用信息的地址如下: 17 新浪微博:http://open.weibo.com 18 腾讯微博:http://dev.t.qq.com 19 QQ空间:http://connect.qq.com/intro/login/ 20 网易微博:http://open.t.163.com 21 搜狐微博:http://open.t.sohu.com 22 豆瓣:http://developers.douban.com 23 人人网:http://dev.renren.com 24 开心网:http://open.kaixin001.com 25 Instapaper:http://www.instapaper.com/main/request_oauth_consumer_token 26 有道云笔记:http://note.youdao.com/open/developguide.html#app 27 facebook:https://developers.facebook.com 28 twitter:https://dev.twitter.com 29 搜狐随身看:https://open.sohu.com 30 QQ好友分享:http://mobile.qq.com/api/ 31 微信:http://open.weixin.qq.com--> 32 33 <ShareSDK 34 AppKey = "api20"/> <!-- AppKey="104972cdd48" "23a9371d3a8"--> 35 36 <SinaWeibo 37 SortId="1" 38 AppKey="3201194191" 39 AppSecret="0334252914651e8f76bad63337b3b78f" 40 Id="1" 41 RedirectUrl="http://appgo.cn" /> 42 43 <TencentWeibo 44 SortId="2" 45 AppKey="801307650" 46 AppSecret="ae36f4ee3946e1cbb98d6965b0b2ff5c" 47 RedirectUri="http://sharesdk.cn" 48 Id="2" /> 49 50 <QZone 51 SortId="3" 52 AppId="100371282" 53 AppKey="aed9b0303e3ed1e27bae87c33761161d" 54 Id="3" 55 RedirectUrl="http://www.shareSDK.cn" /> 56 57 <Renren 58 SortId="4" 59 AppId="226427" 60 ApiKey="fc5b8aed373c4c27a05b712acba0f8c3" 61 Id="4" 62 SecretKey="f29df781abdd4f49beca5a2194676ca4" /> 63 64 </DevInfor>
2、配置AndroidManifest.xml,不同的集成度需要在AndroidManifest.xml中添加的内容也不一样。但是首先你需要添加下面的权限列表:
1 <uses-permission android:name="android.permission.INTERNET" /> 2 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 3 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 4 <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" /> 5 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 6 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 7 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
这些权限将允许你的项目和ShareSDK获取连接网络的权限、获取你的设备网络状态的权限、实现https安全连接的权限、读取手机设备状态的权限和保存必要配置的权限。一般来说,即便不集成ShareSDK,大部分的项目也都会注册申请这些权限。
注意:大家在加入这个"android.permission.WRITE_APN_SETTINGS"权限的时候,可能有些读者的编译器会报错,博主就遇到了这样的情况,这个是ADT Lint工具的问题。
解决的办法是:依照下面的路径“Window —> Preferences —> android—> lint error checking”打开lint的配置页面,然后去掉页面顶部的两个勾选,之后再clean项目就能处理。如下图所示:
3、其次,为了授权操作可以顺利完成,需要在application下注册下面的Activity:
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:
1 <RelativeLayout xmlns: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 6 <Button 7 android:id="@+id/btnLogin" 8 android:layout_width="fill_parent" 9 android:layout_height="44dp" 10 android:layout_above="@+id/btnShareAllGui" 11 android:layout_centerHorizontal="true" 12 android:layout_margin="5dp" 13 android:background="@drawable/btn_back" 14 android:text="用户授权登录" 15 android:textSize="16dp"/> 16 17 <Button 18 android:id="@+id/btnShareAllGui" 19 android:layout_width="fill_parent" 20 android:layout_height="44dp" 21 android:layout_above="@+id/btnShareAll" 22 android:layout_margin="5dp" 23 android:background="@drawable/btn_back" 24 android:text="分享全部(有分享界面)" 25 android:textSize="16dp" /> 26 27 <Button 28 android:id="@+id/btnShareAll" 29 android:layout_width="fill_parent" 30 android:layout_height="44dp" 31 android:layout_alignParentRight="true" 32 android:layout_centerVertical="true" 33 android:layout_margin="5dp" 34 android:background="@drawable/btn_back" 35 android:text="分享全部(无界面,直接分享)" 36 android:textSize="16dp" /> 37 38 <Button 39 android:id="@+id/btnUserInfo" 40 android:layout_width="fill_parent" 41 android:layout_height="44dp" 42 android:layout_below="@+id/btnShareAll" 43 android:layout_margin="5dp" 44 android:layout_marginTop="41dp" 45 android:background="@drawable/btn_back" 46 android:text="获取授权用户资料" 47 android:textSize="16dp" /> 48 49 </RelativeLayout>
5、用户授权登录的布局页面,activity_auth.xml:
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 8 <!--ShareSDK-Core包下封装的一个标题栏--> 9 <cn.sharesdk.framework.TitleLayout 10 android:id="@+id/llTitle" 11 android:layout_width="fill_parent" 12 android:layout_height="wrap_content" 13 android:background="@drawable/title_back" /> 14 15 <LinearLayout 16 android:id="@+id/llBody" 17 android:layout_width="fill_parent" 18 android:layout_height="wrap_content" 19 android:layout_alignParentLeft="true" 20 android:layout_alignParentTop="true" 21 android:layout_marginTop="58dp" 22 android:orientation="vertical" 23 android:padding="10dp" > 24 25 <LinearLayout 26 android:layout_width="fill_parent" 27 android:layout_height="50dp" 28 android:background="@drawable/list_item_first_normal" 29 android:paddingLeft="10dp" 30 android:paddingRight="10dp" > 31 32 <ImageView 33 android:layout_width="30dp" 34 android:layout_height="30dp" 35 android:layout_gravity="center_vertical" 36 android:layout_marginRight="10dp" 37 android:scaleType="centerInside" 38 android:src="@drawable/sina_weibo" /> 39 40 <CheckedTextView 41 android:id="@+id/ctvSw" 42 android:layout_width="fill_parent" 43 android:layout_height="fill_parent" 44 android:layout_gravity="center_vertical" 45 android:drawablePadding="10dp" 46 android:drawableRight="@drawable/cb_drw" 47 android:gravity="center_vertical" 48 android:singleLine="true" 49 android:text="@string/not_yet_authorized" 50 android:textColor="#ff000000" 51 android:textSize="20dp" /> 52 </LinearLayout> 53 54 <LinearLayout 55 android:layout_width="fill_parent" 56 android:layout_height="50dp" 57 android:background="@drawable/list_item_middle_normal" 58 android:paddingLeft="10dp" 59 android:paddingRight="10dp" > 60 61 <ImageView 62 android:layout_width="30dp" 63 android:layout_height="30dp" 64 android:layout_gravity="center_vertical" 65 android:layout_marginRight="10dp" 66 android:scaleType="centerInside" 67 android:src="@drawable/tencent_weibo" /> 68 69 <CheckedTextView 70 android:id="@+id/ctvTc" 71 android:layout_width="fill_parent" 72 android:layout_height="fill_parent" 73 android:layout_gravity="center_vertical" 74 android:drawablePadding="10dp" 75 android:drawableRight="@drawable/cb_drw" 76 android:gravity="center_vertical" 77 android:singleLine="true" 78 android:text="@string/not_yet_authorized" 79 android:textColor="#ff000000" 80 android:textSize="20dp" /> 81 </LinearLayout> 82 83 <LinearLayout 84 android:layout_width="fill_parent" 85 android:layout_height="50dp" 86 android:background="@drawable/list_item_middle_normal" 87 android:paddingLeft="10dp" 88 android:paddingRight="10dp" > 89 90 <ImageView 91 android:layout_width="30dp" 92 android:layout_height="30dp" 93 android:layout_gravity="center_vertical" 94 android:layout_marginRight="10dp" 95 android:scaleType="centerInside" 96 android:src="@drawable/renren" /> 97 98 <CheckedTextView 99 android:id="@+id/ctvRr" 100 android:layout_width="fill_parent" 101 android:layout_height="fill_parent" 102 android:layout_gravity="center_vertical" 103 android:drawablePadding="10dp" 104 android:drawableRight="@drawable/cb_drw" 105 android:gravity="center_vertical" 106 android:singleLine="true" 107 android:text="@string/not_yet_authorized" 108 android:textColor="#ff000000" 109 android:textSize="20dp" /> 110 </LinearLayout> 111 112 <LinearLayout 113 android:layout_width="fill_parent" 114 android:layout_height="50dp" 115 android:background="@drawable/list_item_last_normal" 116 android:paddingLeft="10dp" 117 android:paddingRight="10dp" > 118 119 <ImageView 120 android:layout_width="30dp" 121 android:layout_height="30dp" 122 android:layout_gravity="center_vertical" 123 android:layout_marginRight="10dp" 124 android:scaleType="centerInside" 125 android:src="@drawable/qzone" /> 126 127 <CheckedTextView 128 android:id="@+id/ctvQz" 129 android:layout_width="fill_parent" 130 android:layout_height="fill_parent" 131 android:layout_gravity="center_vertical" 132 android:drawablePadding="10dp" 133 android:drawableRight="@drawable/cb_drw" 134 android:gravity="center_vertical" 135 android:singleLine="true" 136 android:text="@string/not_yet_authorized" 137 android:textColor="#ff000000" 138 android:textSize="20dp" /> 139 </LinearLayout> 140 </LinearLayout> 141 142 </RelativeLayout>
6、获得用户信息布局界面,activity_userinfo.xml:
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 8 <!--ShareSDK-Core包下封装的一个标题栏--> 9 <cn.sharesdk.framework.TitleLayout 10 android:id="@+id/llTitle" 11 android:layout_width="fill_parent" 12 android:layout_height="wrap_content" 13 android:background="@drawable/title_back" /> 14 15 <Button 16 android:id="@+id/btnQz" 17 android:layout_width="fill_parent" 18 android:layout_height="44dp" 19 android:layout_centerVertical="true" 20 android:layout_margin="5dp" 21 android:background="@drawable/btn_back" 22 android:text="@string/get_user_info_qz" 23 android:textSize="16dp" /> 24 25 <Button 26 android:id="@+id/btnRr" 27 android:layout_width="fill_parent" 28 android:layout_height="44dp" 29 android:layout_above="@+id/btnQz" 30 android:layout_margin="5dp" 31 android:background="@drawable/btn_back" 32 android:text="@string/get_user_info_rr" 33 android:textSize="16dp" /> 34 35 <Button 36 android:id="@+id/btnSw" 37 android:layout_width="fill_parent" 38 android:layout_height="44dp" 39 android:layout_above="@+id/btnRr" 40 android:layout_margin="5dp" 41 android:background="@drawable/btn_back" 42 android:text="@string/get_user_info_sw" 43 android:textSize="16dp" /> 44 45 <Button 46 android:id="@+id/btnTc" 47 android:layout_width="fill_parent" 48 android:layout_height="44dp" 49 android:layout_below="@+id/btnQz" 50 android:layout_centerHorizontal="true" 51 android:layout_margin="5dp" 52 android:background="@drawable/btn_back" 53 android:text="@string/get_user_info_tc" 54 android:textSize="16dp" /> 55 56 </RelativeLayout>
7、显示用户获得的信息布局界面,activity_userinfo.xml:
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 8 <!--ShareSDK-Core包下封装的一个标题栏--> 9 <cn.sharesdk.framework.TitleLayout 10 android:id="@+id/llTitle" 11 android:layout_width="fill_parent" 12 android:layout_height="wrap_content" 13 android:background="@drawable/title_back" /> 14 15 <ScrollView 16 android:layout_width="fill_parent" 17 android:layout_height="wrap_content" 18 android:layout_alignParentBottom="true" 19 android:layout_below="@id/llTitle" 20 android:paddingBottom="10dp" 21 android:paddingLeft="10dp" 22 android:paddingTop="10dp" > 23 24 <TextView 25 android:id="@+id/tvJson" 26 android:layout_width="fill_parent" 27 android:layout_height="wrap_content" 28 android:layout_marginRight="10dp" 29 android:autoLink="all" 30 android:background="@drawable/list_item_single_normal" 31 android:textColor="#ff000000" /> 32 </ScrollView> 33 34 </RelativeLayout>
8、主界面入口Activity类,MainActivity.Java:
1 package com.yangyu.activity; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 6 import android.app.Activity; 7 import android.content.Intent; 8 import android.graphics.Bitmap; 9 import android.graphics.Bitmap.CompressFormat; 10 import android.graphics.BitmapFactory; 11 import android.os.Bundle; 12 import android.os.Environment; 13 import android.view.View; 14 import android.view.View.OnClickListener; 15 import android.widget.Button; 16 import cn.sharesdk.framework.AbstractWeibo; 17 import cn.sharesdk.onekeyshare.ShareAllGird; 18 19 import com.yangyu.mysharethings.R; 20 21 /** 22 * @author yangyu 23 * 功能描述:主Activity类,程序的入口类 24 */ 25 public class MainActivity extends Activity implements OnClickListener { 26 //定义图片存放的地址 27 public static String TEST_IMAGE; 28 29 //定义"账号登陆"按钮,"有分享界面按钮","无分享界面"按钮,"得到用户资料"按钮 30 private Button authLoginBtn,shareGuiBtn,shareBtn,getInfoBtn; 31 32 @Override 33 protected void onCreate(Bundle savedInstanceState) { 34 super.onCreate(savedInstanceState); 35 setContentView(R.layout.activity_main); 36 37 //初始化ShareSDK 38 AbstractWeibo.initSDK(this); 39 40 initImagePath(); 41 42 initView(); 43 44 initData(); 45 } 46 47 /** 48 * 初始化组件 49 */ 50 private void initView(){ 51 authLoginBtn = (Button)findViewById(R.id.btnLogin); 52 shareGuiBtn = (Button)findViewById(R.id.btnShareAllGui); 53 shareBtn = (Button)findViewById(R.id.btnShareAll); 54 getInfoBtn = (Button)findViewById(R.id.btnUserInfo); 55 } 56 57 /** 58 * 初始化数据 59 */ 60 private void initData(){ 61 //设置按钮监听事件 62 authLoginBtn.setOnClickListener(this); 63 shareGuiBtn.setOnClickListener(this); 64 shareBtn.setOnClickListener(this); 65 getInfoBtn.setOnClickListener(this); 66 } 67 68 /** 69 * 初始化分享的图片 70 */ 71 private void initImagePath() { 72 try {//判断SD卡中是否存在此文件夹 73 if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) 74 && Environment.getExternalStorageDirectory().exists()) { 75 TEST_IMAGE = Environment.getExternalStorageDirectory().getAbsolutePath() + "/pic.png"; 76 } 77 else { 78 TEST_IMAGE = getApplication().getFilesDir().getAbsolutePath() + "/pic.png"; 79 } 80 File file = new File(TEST_IMAGE); 81 //判断图片是否存此文件夹中 82 if (!file.exists()) { 83 file.createNewFile(); 84 Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.pic); 85 FileOutputStream fos = new FileOutputStream(file); 86 pic.compress(CompressFormat.JPEG, 100, fos); 87 fos.flush(); 88 fos.close(); 89 } 90 } catch(Throwable t) { 91 t.printStackTrace(); 92 TEST_IMAGE = null; 93 } 94 } 95 96 /** 97 * 按钮监听事件 98 */ 99 @Override 100 public void onClick(View v) { 101 switch (v.getId()) { 102 case R.id.btnLogin: 103 startActivity(new Intent(MainActivity.this,AuthActivity.class)); 104 break; 105 case R.id.btnShareAllGui: 106 showGrid(false); 107 break; 108 case R.id.btnShareAll: 109 showGrid(true); 110 break; 111 case R.id.btnUserInfo: 112 // 获取自己的资料 113 Intent i = new Intent(this, GetInforActivity.class); 114 startActivity(i); 115 break; 116 default: 117 break; 118 } 119 120 } 121 122 /** 123 * 使用快捷分享完成图文分享 124 */ 125 private void showGrid(boolean silent) { 126 Intent i = new Intent(this, ShareAllGird.class); 127 // 分享时Notification的图标 128 i.putExtra("notif_icon", R.drawable.ic_launcher); 129 // 分享时Notification的标题 130 i.putExtra("notif_title", this.getString(R.string.app_name)); 131 132 // title标题,在印象笔记、邮箱、信息、微信(包括好友和朋友圈)、人人网和QQ空间使用,否则可以不提供 133 i.putExtra("title", this.getString(R.string.share)); 134 // titleUrl是标题的网络链接,仅在人人网和QQ空间使用,否则可以不提供 135 i.putExtra("titleUrl", "http://sharesdk.cn"); 136 // text是分享文本,所有平台都需要这个字段 137 i.putExtra("text", this.getString(R.string.share_content)); 138 // imagePath是本地的图片路径,所有平台都支持这个字段,不提供,则表示不分享图片 139 i.putExtra("imagePath", MainActivity.TEST_IMAGE); 140 // url仅在微信(包括好友和朋友圈)中使用,否则可以不提供 141 i.putExtra("url", "http://sharesdk.cn"); 142 // thumbPath是缩略图的本地路径,仅在微信(包括好友和朋友圈)中使用,否则可以不提供 143 i.putExtra("thumbPath", MainActivity.TEST_IMAGE); 144 // appPath是待分享应用程序的本地路劲,仅在微信(包括好友和朋友圈)中使用,否则可以不提供 145 i.putExtra("appPath", MainActivity.TEST_IMAGE); 146 // comment是我对这条分享的评论,仅在人人网和QQ空间使用,否则可以不提供 147 i.putExtra("comment", this.getString(R.string.share)); 148 // site是分享此内容的网站名称,仅在QQ空间使用,否则可以不提供 149 i.putExtra("site", this.getString(R.string.app_name)); 150 // siteUrl是分享此内容的网站地址,仅在QQ空间使用,否则可以不提供 151 i.putExtra("siteUrl", "http://sharesdk.cn"); 152 153 // 是否直接分享 154 i.putExtra("silent", silent); 155 this.startActivity(i); 156 } 157 158 /** 159 * 将action转换为String 160 */ 161 public static String actionToString(int action) { 162 switch (action) { 163 case AbstractWeibo.ACTION_AUTHORIZING: return "ACTION_AUTHORIZING"; 164 case AbstractWeibo.ACTION_GETTING_FRIEND_LIST: return "ACTION_GETTING_FRIEND_LIST"; 165 case AbstractWeibo.ACTION_FOLLOWING_USER: return "ACTION_FOLLOWING_USER"; 166 case AbstractWeibo.ACTION_SENDING_DIRECT_MESSAGE: return "ACTION_SENDING_DIRECT_MESSAGE"; 167 case AbstractWeibo.ACTION_TIMELINE: return "ACTION_TIMELINE"; 168 case AbstractWeibo.ACTION_USER_INFOR: return "ACTION_USER_INFOR"; 169 case AbstractWeibo.ACTION_SHARE: return "ACTION_SHARE"; 170 default: { 171 return "UNKNOWN"; 172 } 173 } 174 } 175 176 protected void onDestroy() { 177 //结束ShareSDK的统计功能并释放资源 178 AbstractWeibo.stopSDK(this); 179 super.onDestroy(); 180 } 181 }
集成ShareSDK需要至少在两个地方添加代码,包括:
<1> 在onCreate中插入下面的代码:
//初始化ShareSDK AbstractWeibo.initSDK(this);
这行代码会初始化ShareSDK,此后对ShareSDK的操作都依次为基础。如果不在所有ShareSDK的操作之前调用这行代码,会抛出空指针异常。
<2> 在项目的出口Activity的onDestroy方法的第一行插入下面的代码:
protected void onDestroy() { //结束ShareSDK的统计功能并释放资源 AbstractWeibo.stopSDK(this); super.onDestroy(); }
这行代码会结束ShareSDK的统计功能并释放资源。如果这行代码没有被调用,那么“应用启动次数”的统计将不会准确,因为应用可能从来没有被关闭。
InitSDK是可以重复调用的,其实ShareSDK建议在你不确定的时候调用这个方法,来保证ShareSDK被正确初始化。而stopSDK一旦调用了,就必须重新调用InitSDK才能使用ShareSDK的功能,否则会出现空指针异常。
在这段代码中,还使用到了快捷分享,如下图所示,点击按钮弹出快捷分享界面:
什么是快捷分享呢?快捷分享是ShareSDK提供的一套基于其接口的GUI。通过简单的配置,可以在不考虑平台的情况下,调用很少的代码,就完成分享的操作。快捷分享的jar包放在SDK解压目录的"Libs\ShareSDK-GUI"中,叫做"cn.sharesdk.oneshare.jar"。快捷分享使用了两个Activity,需要在AndroidManifest.xml中注册这两个Activity:
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:
1 package com.yangyu.activity; 2 3 import java.util.HashMap; 4 5 import android.app.Activity; 6 import android.os.Bundle; 7 import android.os.Handler; 8 import android.os.Handler.Callback; 9 import android.os.Message; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.widget.CheckedTextView; 13 import android.widget.Toast; 14 import cn.sharesdk.framework.AbstractWeibo; 15 import cn.sharesdk.framework.TitleLayout; 16 import cn.sharesdk.framework.WeiboActionListener; 17 import cn.sharesdk.renren.Renren; 18 import cn.sharesdk.sina.weibo.SinaWeibo; 19 import cn.sharesdk.tencent.qzone.QZone; 20 import cn.sharesdk.tencent.weibo.TencentWeibo; 21 22 import com.yangyu.mysharethings.R; 23 24 /** 25 * @author yangyu 26 * 功能描述:授权和取消授权Activity,由于UI显示需要授权过的平台显示账户的名称, 27 * 因此此页面事实上展示的是“获取用户资料”和“取消授权”两个功能。 28 */ 29 public class AuthActivity extends Activity implements Callback, OnClickListener, WeiboActionListener { 30 //定义CheckedTextView对象 31 private CheckedTextView sinaCt,qzoneCt,tengxunCt,renrenCt; 32 33 //定义Handler对象 34 private Handler handler; 35 36 //定义标题栏对象 37 private TitleLayout llTitle; 38 39 @Override 40 protected void onCreate(Bundle savedInstanceState) { 41 super.onCreate(savedInstanceState); 42 setContentView(R.layout.activity_auth); 43 44 initView(); 45 46 initData(); 47 } 48 49 /** 50 * 初始化组件 51 */ 52 private void initView(){ 53 //实例化Handler对象并设置信息回调监听接口 54 handler = new Handler(this); 55 56 //得到标题栏对象 57 llTitle = (TitleLayout) findViewById(R.id.llTitle); 58 59 //得到组件对象 60 sinaCt = (CheckedTextView)findViewById(R.id.ctvSw); 61 qzoneCt = (CheckedTextView)findViewById(R.id.ctvQz); 62 tengxunCt = (CheckedTextView)findViewById(R.id.ctvTc); 63 renrenCt = (CheckedTextView)findViewById(R.id.ctvRr); 64 } 65 66 /** 67 * 初始化数据 68 */ 69 private void initData(){ 70 llTitle.getBtnBack().setOnClickListener(new OnClickListener() { 71 @Override 72 public void onClick(View v) { 73 finish(); 74 } 75 }); 76 llTitle.getTvTitle().setText("用户授权登录"); 77 78 //设置监听 79 sinaCt.setOnClickListener(this); 80 qzoneCt.setOnClickListener(this); 81 tengxunCt.setOnClickListener(this); 82 renrenCt.setOnClickListener(this); 83 84 //获取平台列表 85 AbstractWeibo[] weibos = AbstractWeibo.getWeiboList(this); 86 87 for(int i = 0;i < weibos.length;i++){ 88 if (!weibos[i].isValid()) { 89 continue; 90 } 91 92 CheckedTextView ctv = getView(weibos[i]); 93 if (ctv != null) { 94 ctv.setChecked(true); 95 // 得到授权用户的用户名称 96 String userName = weibos[i].getDb().get("nickname"); 97 if (userName == null || userName.length() <= 0 || "null".equals(userName)) { 98 // 如果平台已经授权却没有拿到帐号名称,则自动获取用户资料,以获取名称 99 userName = getWeiboName(weibos[i]); 100 //添加平台事件监听 101 weibos[i].setWeiboActionListener(this); 102 //显示用户资料,null表示显示自己的资料 103 weibos[i].showUser(null); 104 } 105 ctv.setText(userName); 106 } 107 } 108 } 109 110 /** 111 * 在CheckedTextView组件中显示授权用户的名称 112 */ 113 private CheckedTextView getView(AbstractWeibo weibo) { 114 if (weibo == null) { 115 return null; 116 } 117 118 String name = weibo.getName(); 119 if (name == null) { 120 return null; 121 } 122 123 View v = null; 124 if (SinaWeibo.NAME.equals(name)) { 125 v = findViewById(R.id.ctvSw); 126 } 127 else if (TencentWeibo.NAME.equals(name)) { 128 v = findViewById(R.id.ctvTc); 129 } 130 else if (Renren.NAME.equals(name)) { 131 v = findViewById(R.id.ctvRr); 132 } 133 else if (QZone.NAME.equals(name)) { 134 v = findViewById(R.id.ctvQz); 135 } 136 137 if (v == null) { 138 return null; 139 } 140 141 if (! (v instanceof CheckedTextView)) { 142 return null; 143 } 144 145 return (CheckedTextView) v; 146 } 147 148 /** 149 * 得到授权用户的用户名称 150 */ 151 private String getWeiboName(AbstractWeibo weibo) { 152 if (weibo == null) { 153 return null; 154 } 155 156 String name = weibo.getName(); 157 if (name == null) { 158 return null; 159 } 160 161 int res = 0; 162 if (SinaWeibo.NAME.equals(name)) { 163 res = R.string.sinaweibo; 164 } 165 else if (TencentWeibo.NAME.equals(name)) { 166 res = R.string.tencentweibo; 167 } 168 else if (Renren.NAME.equals(name)) { 169 res = R.string.renren; 170 } 171 else if (QZone.NAME.equals(name)) { 172 res = R.string.qzone; 173 } 174 175 if (res == 0) { 176 return name; 177 } 178 return this.getResources().getString(res); 179 } 180 181 /** 182 * 授权和取消授权的按钮点击监听事件 183 */ 184 @Override 185 public void onClick(View v) { 186 AbstractWeibo weibo = getWeibo(v.getId()); 187 188 CheckedTextView ctv = (CheckedTextView) v; 189 if (weibo == null) { 190 ctv.setChecked(false); 191 ctv.setText(R.string.not_yet_authorized); 192 return; 193 } 194 195 if (weibo.isValid()) { 196 weibo.removeAccount(); 197 ctv.setChecked(false); 198 ctv.setText(R.string.not_yet_authorized); 199 return; 200 } 201 202 weibo.setWeiboActionListener(this); 203 weibo.showUser(null); 204 } 205 206 /** 207 * 获得授权 208 */ 209 private AbstractWeibo getWeibo(int vid) { 210 String name = null; 211 switch (vid) { 212 // 进入新浪微博的授权页面 213 case R.id.ctvSw: 214 name = SinaWeibo.NAME; 215 break; 216 // 进入腾讯微博的授权页面 217 case R.id.ctvTc: 218 name = TencentWeibo.NAME; 219 break; 220 // 进入人人网的授权页面 221 case R.id.ctvRr: 222 name = Renren.NAME; 223 break; 224 // 进入QQ空间的授权页面 225 case R.id.ctvQz: 226 name = QZone.NAME; 227 break; 228 } 229 230 if (name != null) { 231 return AbstractWeibo.getWeibo(this, name); 232 } 233 return null; 234 } 235 236 /** 237 * 授权成功的回调 238 * weibo - 回调的平台 239 * action - 操作的类型 240 * res - 请求的数据通过res返回 241 */ 242 @Override 243 public void onComplete(AbstractWeibo weibo, int action,HashMap<String, Object> res) { 244 Message msg = new Message(); 245 msg.arg1 = 1; 246 msg.arg2 = action; 247 msg.obj = weibo; 248 handler.sendMessage(msg); 249 } 250 251 /** 252 * 授权失败的回调 253 */ 254 @Override 255 public void onError(AbstractWeibo weibo, int action, Throwable t) { 256 t.printStackTrace(); 257 258 Message msg = new Message(); 259 msg.arg1 = 2; 260 msg.arg2 = action; 261 msg.obj = weibo; 262 handler.sendMessage(msg); 263 } 264 265 /** 266 * 取消授权的回调 267 */ 268 @Override 269 public void onCancel(AbstractWeibo weibo, int action) { 270 Message msg = new Message(); 271 msg.arg1 = 3; 272 msg.arg2 = action; 273 msg.obj = weibo; 274 handler.sendMessage(msg); 275 } 276 277 /** 278 * 处理从授权页面返回的结果 279 * 280 * 如果获取到用户的名称,则显示名称;否则如果已经授权,则显示平台名称 281 */ 282 @Override 283 public boolean handleMessage(Message msg) { 284 AbstractWeibo weibo = (AbstractWeibo) msg.obj; 285 String text = MainActivity.actionToString(msg.arg2); 286 287 switch (msg.arg1) { 288 case 1: { // 成功 289 text = weibo.getName() + " completed at " + text; 290 Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 291 } 292 break; 293 case 2: { // 失败 294 text = weibo.getName() + " caught error at " + text; 295 Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 296 return false; 297 } 298 case 3: { // 取消 299 text = weibo.getName() + " canceled at " + text; 300 Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 301 return false; 302 } 303 } 304 305 CheckedTextView ctv = getView(weibo); 306 if (ctv != null) { 307 ctv.setChecked(true); 308 String userName = weibo.getDb().get("nickname"); // getAuthedUserName(); 309 if (userName == null || userName.length() <= 0 310 || "null".equals(userName)) { 311 userName = getWeiboName(weibo); 312 } 313 ctv.setText(userName); 314 } 315 return false; 316 } 317 }
10、获取用户信息界面,GetInfoActivity.java:
1 package com.yangyu.activity; 2 3 import java.util.HashMap; 4 5 import android.app.Activity; 6 import android.content.Intent; 7 import android.os.Bundle; 8 import android.os.Handler; 9 import android.os.Handler.Callback; 10 import android.os.Message; 11 import android.view.View; 12 import android.view.View.OnClickListener; 13 import android.widget.Button; 14 import android.widget.Toast; 15 import cn.sharesdk.framework.AbstractWeibo; 16 import cn.sharesdk.framework.TitleLayout; 17 import cn.sharesdk.framework.WeiboActionListener; 18 import cn.sharesdk.renren.Renren; 19 import cn.sharesdk.sina.weibo.SinaWeibo; 20 import cn.sharesdk.tencent.qzone.QZone; 21 import cn.sharesdk.tencent.weibo.TencentWeibo; 22 23 import com.yangyu.mysharethings.R; 24 25 /** 26 * @author yangyu 27 * 功能描述:获取用户资料 28 * 29 * 启动页面时传递一个int类型的字段type,用于标记获取自己的资料(type = 0)还是别人的资料(type = 1)。 30 * 如果尝试获取别人的资料,示例代码会获取不同平台Share SDK的官方帐号的资料。 31 * 32 * 如果资料获取成功,会通过{@link ShowInforPage}展示 33 */ 34 public class GetInforActivity extends Activity implements Callback, OnClickListener, WeiboActionListener { 35 36 //定义标题栏布局对象 37 private TitleLayout llTitle; 38 39 private Button sinaBt,renrenBt,qzoneBt,tengxunBt; 40 41 private Handler handler; 42 43 protected void onCreate(Bundle savedInstanceState) { 44 super.onCreate(savedInstanceState); 45 46 handler = new Handler(this); 47 48 setContentView(R.layout.activity_userinfo); 49 50 initView(); 51 52 initData(); 53 54 } 55 56 /** 57 * 初始化组件 58 */ 59 private void initView(){ 60 //得到标题栏对象 61 llTitle = (TitleLayout) findViewById(R.id.llTitle); 62 63 //得到按钮对象 64 sinaBt = (Button) findViewById(R.id.btnSw); 65 renrenBt = (Button) findViewById(R.id.btnRr); 66 qzoneBt = (Button) findViewById(R.id.btnQz); 67 tengxunBt = (Button) findViewById(R.id.btnTc); 68 69 70 } 71 72 /** 73 * 初始化数据 74 */ 75 private void initData(){ 76 //标题栏设置返回按钮监听 77 llTitle.getBtnBack().setOnClickListener(this); 78 //设置标题栏的标题文本 79 llTitle.getTvTitle().setText(R.string.get_my_info); 80 81 //设置监听 82 sinaBt.setOnClickListener(this); 83 renrenBt.setOnClickListener(this); 84 qzoneBt.setOnClickListener(this); 85 tengxunBt.setOnClickListener(this); 86 } 87 88 /** 89 * 点击按钮获取授权用户的资料 90 */ 91 @Override 92 public void onClick(View v) { 93 if (v.equals(llTitle.getBtnBack())) { 94 finish(); 95 return; 96 } 97 98 String name = null; 99 100 switch (v.getId()) { 101 case R.id.btnSw: 102 name = SinaWeibo.NAME; 103 break; 104 case R.id.btnTc: 105 name = TencentWeibo.NAME; 106 break; 107 case R.id.btnRr: 108 name = Renren.NAME; 109 break; 110 case R.id.btnQz: 111 name = QZone.NAME; 112 break; 113 } 114 115 if (name != null) { 116 AbstractWeibo weibo = AbstractWeibo.getWeibo(this, name); 117 weibo.setWeiboActionListener(this); 118 String account = null; 119 120 weibo.showUser(account); 121 } 122 } 123 124 public void onComplete(AbstractWeibo weibo, int action,HashMap<String, Object> res) { 125 Message msg = new Message(); 126 msg.arg1 = 1; 127 msg.arg2 = action; 128 msg.obj = weibo; 129 handler.sendMessage(msg); 130 131 Message msg2 = new Message(); 132 msg2.what = 1; 133 JsonUtils ju = new JsonUtils(); 134 String json = ju.fromHashMap(res); 135 msg2.obj = ju.format(json); 136 handler.sendMessage(msg2); 137 } 138 139 public void onError(AbstractWeibo weibo, int action, Throwable t) { 140 t.printStackTrace(); 141 142 Message msg = new Message(); 143 msg.arg1 = 2; 144 msg.arg2 = action; 145 msg.obj = weibo; 146 handler.sendMessage(msg); 147 } 148 149 public void onCancel(AbstractWeibo weibo, int action) { 150 Message msg = new Message(); 151 msg.arg1 = 3; 152 msg.arg2 = action; 153 msg.obj = weibo; 154 handler.sendMessage(msg); 155 } 156 157 /** 处理操作结果 */ 158 public boolean handleMessage(Message msg) { 159 switch(msg.what) { 160 case 1: { 161 Intent i = new Intent(this, ShowInforActivity.class); 162 i.putExtra("data", String.valueOf(msg.obj)); 163 startActivity(i); 164 } 165 break; 166 default: { 167 AbstractWeibo weibo = (AbstractWeibo) msg.obj; 168 String text = MainActivity.actionToString(msg.arg2); 169 switch (msg.arg1) { 170 case 1: { // 成功 171 text = weibo.getName() + " completed at " + text; 172 } 173 break; 174 case 2: { // 失败 175 text = weibo.getName() + " caught error at " + text; 176 } 177 break; 178 case 3: { // 取消 179 text = weibo.getName() + " canceled at " + text; 180 } 181 break; 182 } 183 184 Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 185 } 186 break; 187 } 188 return false; 189 } 190 191 192 }
11、显示用户信息界面,ShowInfoActivity.java
1 package com.yangyu.activity; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.view.View; 6 import android.view.View.OnClickListener; 7 import android.widget.TextView; 8 import cn.sharesdk.framework.TitleLayout; 9 10 import com.yangyu.mysharethings.R; 11 12 /** 13 * @author yangyu 14 * 功能描述:显示用户信息资料 15 */ 16 public class ShowInforActivity extends Activity implements OnClickListener { 17 private TitleLayout llTitle; 18 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_show_userinfo); 22 23 llTitle = (TitleLayout) findViewById(R.id.llTitle); 24 llTitle.getBtnBack().setOnClickListener(this); 25 llTitle.getTvTitle().setText("用户资料"); 26 27 TextView tvJson = (TextView) findViewById(R.id.tvJson); 28 tvJson.setText(getIntent().getStringExtra("data")); 29 } 30 31 @Override 32 public void onClick(View v) { 33 if (v.equals(llTitle.getBtnBack())) { 34 finish(); 35 } 36 } 37 38 }
12、这里还定义了一个Json解析类去读取授权用户的信息,JsonUtils.java:
package com.yangyu.activity; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; /** * @author yangyu * 功能描述:这是一个简易的Json-HashMap转换工具,可以将普通的json数据(字符串) * 转换为一个HashMap<Srting, Object>表格,也可以反过来操作。此外还支 * 持将json数据格式化。 */ public class JsonUtils { /** * 将指定的json数据转成 HashMap<String, Object>对象 */ public HashMap<String, Object> fromJson(String jsonStr) { try { if (jsonStr.startsWith("[") && jsonStr.endsWith("]")) { jsonStr = "{\"fakelist\":" + jsonStr + "}"; } JSONObject json = new JSONObject(jsonStr); return fromJson(json); } catch (Throwable t) { t.printStackTrace(); } return new HashMap<String, Object>(); } private HashMap<String, Object> fromJson(JSONObject json) throws JSONException { HashMap<String, Object> map = new HashMap<String, Object>(); @SuppressWarnings("unchecked") Iterator<String> iKey = json.keys(); while(iKey.hasNext()) { String key = iKey.next(); Object value = json.opt(key); if (JSONObject.NULL.equals(value)) { value = null; } if (value != null) { if (value instanceof JSONObject) { value = fromJson((JSONObject)value); } else if (value instanceof JSONArray) { value = fromJson((JSONArray)value); } map.put(key, value); } } return map; } private ArrayList<Object> fromJson(JSONArray array) throws JSONException { ArrayList<Object> list = new ArrayList<Object>(); for (int i = 0, size = array.length(); i < size; i++) { Object value = array.opt(i); if (value instanceof JSONObject) { value = fromJson((JSONObject)value); } else if (value instanceof JSONArray) { value = fromJson((JSONArray)value); } list.add(value); } return list; } /** * 将指定的HashMap<String, Object>对象转成json数据 */ public String fromHashMap(HashMap<String, Object> map) { try { return getJSONObject(map).toString(); } catch (Throwable t) { t.printStackTrace(); } return ""; } @SuppressWarnings("unchecked") private JSONObject getJSONObject(HashMap<String, Object> map) throws JSONException { JSONObject json = new JSONObject(); for (Entry<String, Object> entry : map.entrySet()) { Object value = entry.getValue(); if (value instanceof HashMap<?, ?>) { value = getJSONObject((HashMap<String, Object>)value); } else if (value instanceof ArrayList<?>) { value = getJSONArray((ArrayList<Object>)value); } json.put(entry.getKey(), value); } return json; } @SuppressWarnings("unchecked") private JSONArray getJSONArray(ArrayList<Object> list) throws JSONException { JSONArray array = new JSONArray(); for (Object value : list) { if (value instanceof HashMap<?, ?>) { value = getJSONObject((HashMap<String, Object>)value); } else if (value instanceof ArrayList<?>) { value = getJSONArray((ArrayList<Object>)value); } array.put(value); } return array; } /** * 格式化一个json串 */ public String format(String jsonStr) { try { return format("", fromJson(jsonStr)); } catch (Throwable t) { t.printStackTrace(); } return ""; } @SuppressWarnings("unchecked") private String format(String sepStr, HashMap<String, Object> map) { StringBuffer sb = new StringBuffer(); sb.append("{\n"); String mySepStr = sepStr + "\t"; int i = 0; for (Entry<String, Object> entry : map.entrySet()) { if (i > 0) { sb.append(",\n"); } sb.append(mySepStr).append(‘\"‘).append(entry.getKey()).append("\":"); Object value = entry.getValue(); if (value instanceof HashMap<?, ?>) { sb.append(format(mySepStr, (HashMap<String, Object>)value)); } else if (value instanceof ArrayList<?>) { sb.append(format(mySepStr, (ArrayList<Object>)value)); } else if (value instanceof String) { sb.append(‘\"‘).append(value).append(‘\"‘); } else { sb.append(value); } i++; } sb.append(‘\n‘).append(sepStr).append(‘}‘); return sb.toString(); } @SuppressWarnings("unchecked") private String format(String sepStr, ArrayList<Object> list) { StringBuffer sb = new StringBuffer(); sb.append("[\n"); String mySepStr = sepStr + "\t"; int i = 0; for (Object value : list) { if (i > 0) { sb.append(",\n"); } sb.append(mySepStr); if (value instanceof HashMap<?, ?>) { sb.append(format(mySepStr, (HashMap<String, Object>)value)); } else if (value instanceof ArrayList<?>) { sb.append(format(mySepStr, (ArrayList<Object>)value)); } else if (value instanceof String) { sb.append(‘\"‘).append(value).append(‘\"‘); } else { sb.append(value); } i++; } sb.append(‘\n‘).append(sepStr).append(‘]‘); return sb.toString(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
以上是关于转:Android实现第三方授权登录,分享以及获取用户资料的主要内容,如果未能解决你的问题,请参考以下文章
Android开发实现QQ三方登录 标签: android开发qq三方登录