世事洞明皆学问,人情练达即文章。这篇文章主要讲述转: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。
【转(Android实现第三方授权登录,分享以及获取用户资料)】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< !--说明: 41、表格中的第一项 5< ShareSDK AppKey="api20" /> 6是必须的,其中的AppKey是你在Share SDK上注册的开发者帐号的AppKey 7 82、所有集成到你项目的平台都应该为其在表格中填写相对应的开发者信息,以新浪微博为例: 9< SinaWeibo 10SortId="此平台在分享列表中的位置,由开发者自行定义,可以是任何整型数字,数值越大越靠后" 11AppKey="填写你在新浪微博上注册的AppKey" 12AppSecret="填写你在新浪微博上注册到的AppKey" 13Id="自定义字段,整形,用于你项目中对此平台的识别符" 14RedirectUrl="填写你在新浪微博上注册的RedirectUrl" /> 15 16各个平台注册应用信息的地址如下: 17新浪微博:http://open.weibo.com 18腾讯微博:http://dev.t.qq.com 19QQ空间: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 25Instapaper:http://www.instapaper.com/main/request_oauth_consumer_token 26有道云笔记:http://note.youdao.com/open/developguide.html#app 27facebook:https://developers.facebook.com 28twitter:https://dev.twitter.com 29搜狐随身看:https://open.sohu.com 30QQ好友分享:http://mobile.qq.com/api/ 31微信:http://open.weixin.qq.com--> 32 33< ShareSDK 34AppKey = "api20"/> < !-- AppKey="104972cdd48" "23a9371d3a8"--> 35 36< SinaWeibo 37SortId="1" 38AppKey="3201194191" 39AppSecret="0334252914651e8f76bad63337b3b78f" 40Id="1" 41RedirectUrl="http://appgo.cn" /> 42 43< TencentWeibo 44SortId="2" 45AppKey="801307650" 46AppSecret="ae36f4ee3946e1cbb98d6965b0b2ff5c" 47RedirectUri="http://sharesdk.cn" 48Id="2" /> 49 50< QZone 51SortId="3" 52AppId="100371282" 53AppKey="aed9b0303e3ed1e27bae87c33761161d" 54Id="3" 55RedirectUrl="http://www.shareSDK.cn" /> 56 57< Renren 58SortId="4" 59AppId="226427" 60ApiKey="fc5b8aed373c4c27a05b712acba0f8c3" 61Id="4" 62SecretKey="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 2android:name="cn.sharesdk.framework.AuthorizeActivity" 3android:configChanges="keyboardHidden|orientation" 4android:screenOrientation="portrait" 5android:theme="@android:style/Theme.Translucent.NoTitleBar" 6android: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" 2xmlns:tools="http://schemas.android.com/tools" 3android:layout_width="match_parent" 4android:layout_height="match_parent" > 5 6< Button 7android:id="@+id/btnLogin" 8android:layout_width="fill_parent" 9android:layout_height="44dp" 10android:layout_above="@+id/btnShareAllGui" 11android:layout_centerHorizontal="true" 12android:layout_margin="5dp" 13android:background="@drawable/btn_back" 14android:text="用户授权登录" 15android:textSize="16dp"/> 16 17< Button 18android:id="@+id/btnShareAllGui" 19android:layout_width="fill_parent" 20android:layout_height="44dp" 21android:layout_above="@+id/btnShareAll" 22android:layout_margin="5dp" 23android:background="@drawable/btn_back" 24android:text="分享全部(有分享界面)" 25android:textSize="16dp" /> 26 27< Button 28android:id="@+id/btnShareAll" 29android:layout_width="fill_parent" 30android:layout_height="44dp" 31android:layout_alignParentRight="true" 32android:layout_centerVertical="true" 33android:layout_margin="5dp" 34android:background="@drawable/btn_back" 35android:text="分享全部(无界面,直接分享)" 36android:textSize="16dp" /> 37 38< Button 39android:id="@+id/btnUserInfo" 40android:layout_width="fill_parent" 41android:layout_height="44dp" 42android:layout_below="@+id/btnShareAll" 43android:layout_margin="5dp" 44android:layout_marginTop="41dp" 45android:background="@drawable/btn_back" 46android:text="获取授权用户资料" 47android: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" 3android:layout_width="fill_parent" 4android:layout_height="fill_parent" 5android:background="#fff5f5f5" 6android:orientation="vertical" > 7 8< !--ShareSDK-Core包下封装的一个标题栏--> 9< cn.sharesdk.framework.TitleLayout 10android:id="@+id/llTitle" 11android:layout_width="fill_parent" 12android:layout_height="wrap_content" 13android:background="@drawable/title_back" /> 14 15< LinearLayout 16android:id="@+id/llBody" 17android:layout_width="fill_parent" 18android:layout_height="wrap_content" 19android:layout_alignParentLeft="true" 20android:layout_alignParentTop="true" 21android:layout_marginTop="58dp" 22android:orientation="vertical" 23android:padding="10dp" > 24 25< LinearLayout 26android:layout_width="fill_parent" 27android:layout_height="50dp" 28android:background="@drawable/list_item_first_normal" 29android:paddingLeft="10dp" 30android:paddingRight="10dp" > 31 32< ImageView 33android:layout_width="30dp" 34android:layout_height="30dp" 35android:layout_gravity="center_vertical" 36android:layout_marginRight="10dp" 37android:scaleType="centerInside" 38android:src="https://www.songbingjia.com/android/@drawable/sina_weibo" /> 39 40< CheckedTextView 41android:id="@+id/ctvSw" 42android:layout_width="fill_parent" 43android:layout_height="fill_parent" 44android:layout_gravity="center_vertical" 45android:drawablePadding="10dp" 46android:drawableRight="@drawable/cb_drw" 47android:gravity="center_vertical" 48android:singleLine="true" 49android:text="@string/not_yet_authorized" 50android:textColor="#ff000000" 51android:textSize="20dp" /> 52< /LinearLayout> 53 54< LinearLayout 55android:layout_width="fill_parent" 56android:layout_height="50dp" 57android:background="@drawable/list_item_middle_normal" 58android:paddingLeft="10dp" 59android:paddingRight="10dp" > 60 61< ImageView 62android:layout_width="30dp" 63android:layout_height="30dp" 64android:layout_gravity="center_vertical" 65android:layout_marginRight="10dp" 66android:scaleType="centerInside" 67android:src="https://www.songbingjia.com/android/@drawable/tencent_weibo" /> 68 69< CheckedTextView 70android:id="@+id/ctvTc" 71android:layout_width="fill_parent" 72android:layout_height="fill_parent" 73android:layout_gravity="center_vertical" 74android:drawablePadding="10dp" 75android:drawableRight="@drawable/cb_drw" 76android:gravity="center_vertical" 77android:singleLine="true" 78android:text="@string/not_yet_authorized" 79android:textColor="#ff000000" 80android:textSize="20dp" /> 81< /LinearLayout> 82 83< LinearLayout 84android:layout_width="fill_parent" 85android:layout_height="50dp" 86android:background="@drawable/list_item_middle_normal" 87android:paddingLeft="10dp" 88android:paddingRight="10dp" > 89 90< ImageView 91android:layout_width="30dp" 92android:layout_height="30dp" 93android:layout_gravity="center_vertical" 94android:layout_marginRight="10dp" 95android:scaleType="centerInside" 96android:src="https://www.songbingjia.com/android/@drawable/renren" /> 97 98< CheckedTextView 99android:id="@+id/ctvRr" 100android:layout_width="fill_parent" 101android:layout_height="fill_parent" 102android:layout_gravity="center_vertical" 103android:drawablePadding="10dp" 104android:drawableRight="@drawable/cb_drw" 105android:gravity="center_vertical" 106android:singleLine="true" 107android:text="@string/not_yet_authorized" 108android:textColor="#ff000000" 109android:textSize="20dp" /> 110< /LinearLayout> 111 112< LinearLayout 113android:layout_width="fill_parent" 114android:layout_height="50dp" 115android:background="@drawable/list_item_last_normal" 116android:paddingLeft="10dp" 117android:paddingRight="10dp" > 118 119< ImageView 120android:layout_width="30dp" 121android:layout_height="30dp" 122android:layout_gravity="center_vertical" 123android:layout_marginRight="10dp" 124android:scaleType="centerInside" 125android:src="https://www.songbingjia.com/android/@drawable/qzone" /> 126 127< CheckedTextView 128android:id="@+id/ctvQz" 129android:layout_width="fill_parent" 130android:layout_height="fill_parent" 131android:layout_gravity="center_vertical" 132android:drawablePadding="10dp" 133android:drawableRight="@drawable/cb_drw" 134android:gravity="center_vertical" 135android:singleLine="true" 136android:text="@string/not_yet_authorized" 137android:textColor="#ff000000" 138android: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" 3android:layout_width="fill_parent" 4android:layout_height="fill_parent" 5android:background="#fff5f5f5" 6android:orientation="vertical" > 7 8< !--ShareSDK-Core包下封装的一个标题栏--> 9< cn.sharesdk.framework.TitleLayout 10android:id="@+id/llTitle" 11android:layout_width="fill_parent" 12android:layout_height="wrap_content" 13android:background="@drawable/title_back" /> 14 15< Button 16android:id="@+id/btnQz" 17android:layout_width="fill_parent" 18android:layout_height="44dp" 19android:layout_centerVertical="true" 20android:layout_margin="5dp" 21android:background="@drawable/btn_back" 22android:text="@string/get_user_info_qz" 23android:textSize="16dp" /> 24 25< Button 26android:id="@+id/btnRr" 27android:layout_width="fill_parent" 28android:layout_height="44dp" 29android:layout_above="@+id/btnQz" 30android:layout_margin="5dp" 31android:background="@drawable/btn_back" 32android:text="@string/get_user_info_rr" 33android:textSize="16dp" /> 34 35< Button 36android:id="@+id/btnSw" 37android:layout_width="fill_parent" 38android:layout_height="44dp" 39android:layout_above="@+id/btnRr" 40android:layout_margin="5dp" 41android:background="@drawable/btn_back" 42android:text="@string/get_user_info_sw" 43android:textSize="16dp" /> 44 45< Button 46android:id="@+id/btnTc" 47android:layout_width="fill_parent" 48android:layout_height="44dp" 49android:layout_below="@+id/btnQz" 50android:layout_centerHorizontal="true" 51android:layout_margin="5dp" 52android:background="@drawable/btn_back" 53android:text="@string/get_user_info_tc" 54android: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" 3android:layout_width="fill_parent" 4android:layout_height="fill_parent" 5android:background="#fff5f5f5" 6android:orientation="vertical" > 7 8< !--ShareSDK-Core包下封装的一个标题栏--> 9< cn.sharesdk.framework.TitleLayout 10android:id="@+id/llTitle" 11android:layout_width="fill_parent" 12android:layout_height="wrap_content" 13android:background="@drawable/title_back" /> 14 15< ScrollView 16android:layout_width="fill_parent" 17android:layout_height="wrap_content" 18android:layout_alignParentBottom="true" 19android:layout_below="@id/llTitle" 20android:paddingBottom="10dp" 21android:paddingLeft="10dp" 22android:paddingTop="10dp" > 23 24< TextView 25android:id="@+id/tvJson" 26android:layout_width="fill_parent" 27android:layout_height="wrap_content" 28android:layout_marginRight="10dp" 29android:autoLink="all" 30android:background="@drawable/list_item_single_normal" 31android: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//定义图片存放的地址 27public static String TEST_IMAGE; 28 29//定义"账号登陆"按钮,"有分享界面按钮","无分享界面"按钮,"得到用户资料"按钮 30private Button authLoginBtn,shareGuiBtn,shareBtn,getInfoBtn; 31 32@Override 33protected void onCreate(Bundle savedInstanceState) { 34super.onCreate(savedInstanceState); 35setContentView(R.layout.activity_main); 36 37//初始化ShareSDK 38AbstractWeibo.initSDK(this); 39 40initImagePath(); 41 42initView(); 43 44initData(); 45} 46 47/** 48* 初始化组件 49*/ 50private void initView(){ 51authLoginBtn = (Button)findViewById(R.id.btnLogin); 52shareGuiBtn = (Button)findViewById(R.id.btnShareAllGui); 53shareBtn = (Button)findViewById(R.id.btnShareAll); 54getInfoBtn = (Button)findViewById(R.id.btnUserInfo); 55} 56 57/** 58* 初始化数据 59*/ 60private void initData(){ 61//设置按钮监听事件 62authLoginBtn.setOnClickListener(this); 63shareGuiBtn.setOnClickListener(this); 64shareBtn.setOnClickListener(this); 65getInfoBtn.setOnClickListener(this); 66} 67 68/** 69* 初始化分享的图片 70*/ 71private void initImagePath() { 72try {//判断SD卡中是否存在此文件夹 73if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) 74& & Environment.getExternalStorageDirectory().exists()) { 75TEST_IMAGE = Environment.getExternalStorageDirectory().getAbsolutePath() + "/pic.png"; 76} 77else { 78TEST_IMAGE = getApplication().getFilesDir().getAbsolutePath() + "/pic.png"; 79} 80File file = new File(TEST_IMAGE); 81//判断图片是否存此文件夹中 82if (!file.exists()) { 83file.createNewFile(); 84Bitmap pic = BitmapFactory.decodeResource(getResources(), R.drawable.pic); 85FileOutputStream fos = new FileOutputStream(file); 86pic.compress(CompressFormat.JPEG, 100, fos); 87fos.flush(); 88fos.close(); 89} 90} catch(Throwable t) { 91t.printStackTrace(); 92TEST_IMAGE = null; 93} 94} 95 96/** 97* 按钮监听事件 98*/ 99@Override 100public void onClick(View v) { 101switch (v.getId()) { 102case R.id.btnLogin: 103startActivity(new Intent(MainActivity.this,AuthActivity.class)); 104break; 105case R.id.btnShareAllGui: 106showGrid(false); 107break; 108case R.id.btnShareAll: 109showGrid(true); 110break; 111case R.id.btnUserInfo: 112// 获取自己的资料 113Intent i = new Intent(this, GetInforActivity.class); 114startActivity(i); 115break; 116default: 117break; 118} 119 120} 121 122/** 123* 使用快捷分享完成图文分享 124*/ 125private void showGrid(boolean silent) { 126Intent i = new Intent(this, ShareAllGird.class); 127// 分享时Notification的图标 128i.putExtra("notif_icon", R.drawable.ic_launcher); 129// 分享时Notification的标题 130i.putExtra("notif_title", this.getString(R.string.app_name)); 131 132// title标题,在印象笔记、邮箱、信息、微信(包括好友和朋友圈)、人人网和QQ空间使用,否则可以不提供 133i.putExtra("title", this.getString(R.string.share)); 134// titleUrl是标题的网络链接,仅在人人网和QQ空间使用,否则可以不提供 135i.putExtra("titleUrl", "http://sharesdk.cn"); 136// text是分享文本,所有平台都需要这个字段 137i.putExtra("text", this.getString(R.string.share_content)); 138// imagePath是本地的图片路径,所有平台都支持这个字段,不提供,则表示不分享图片 139i.putExtra("imagePath", MainActivity.TEST_IMAGE); 140// url仅在微信(包括好友和朋友圈)中使用,否则可以不提供 141i.putExtra("url", "http://sharesdk.cn"); 142// thumbPath是缩略图的本地路径,仅在微信(包括好友和朋友圈)中使用,否则可以不提供 143i.putExtra("thumbPath", MainActivity.TEST_IMAGE); 144// appPath是待分享应用程序的本地路劲,仅在微信(包括好友和朋友圈)中使用,否则可以不提供 145i.putExtra("appPath", MainActivity.TEST_IMAGE); 146// comment是我对这条分享的评论,仅在人人网和QQ空间使用,否则可以不提供 147i.putExtra("comment", this.getString(R.string.share)); 148// site是分享此内容的网站名称,仅在QQ空间使用,否则可以不提供 149i.putExtra("site", this.getString(R.string.app_name)); 150// siteUrl是分享此内容的网站地址,仅在QQ空间使用,否则可以不提供 151i.putExtra("siteUrl", "http://sharesdk.cn"); 152 153// 是否直接分享 154i.putExtra("silent", silent); 155this.startActivity(i); 156} 157 158/** 159* 将action转换为String 160*/ 161public static String actionToString(int action) { 162switch (action) { 163case AbstractWeibo.ACTION_AUTHORIZING: return "ACTION_AUTHORIZING"; 164case AbstractWeibo.ACTION_GETTING_FRIEND_LIST: return "ACTION_GETTING_FRIEND_LIST"; 165case AbstractWeibo.ACTION_FOLLOWING_USER: return "ACTION_FOLLOWING_USER"; 166case AbstractWeibo.ACTION_SENDING_DIRECT_MESSAGE: return "ACTION_SENDING_DIRECT_MESSAGE"; 167case AbstractWeibo.ACTION_TIMELINE: return "ACTION_TIMELINE"; 168case AbstractWeibo.ACTION_USER_INFOR: return "ACTION_USER_INFOR"; 169case AbstractWeibo.ACTION_SHARE: return "ACTION_SHARE"; 170default: { 171return "UNKNOWN"; 172} 173} 174} 175 176protected void onDestroy() { 177//结束ShareSDK的统计功能并释放资源 178AbstractWeibo.stopSDK(this); 179super.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 2android:name="cn.sharesdk.onekeyshare.ShareAllGird" 3android:configChanges="keyboardHidden|orientation" 4android:screenOrientation="portrait" 5android:theme="@android:style/Theme.Translucent.NoTitleBar" 6android:windowSoftInputMode="adjustPan|stateHidden" /> 7< activity 8android:name="cn.sharesdk.onekeyshare.SharePage" 9android:configChanges="keyboardHidden|orientation" 10android:screenOrientation="portrait" 11android: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对象 31private CheckedTextView sinaCt,qzoneCt,tengxunCt,renrenCt; 32 33//定义Handler对象 34private Handler handler; 35 36//定义标题栏对象 37private TitleLayout llTitle; 38 39@Override 40protected void onCreate(Bundle savedInstanceState) { 41super.onCreate(savedInstanceState); 42setContentView(R.layout.activity_auth); 43 44initView(); 45 46initData(); 47} 48 49/** 50* 初始化组件 51*/ 52private void initView(){ 53//实例化Handler对象并设置信息回调监听接口 54handler = new Handler(this); 55 56//得到标题栏对象 57llTitle = (TitleLayout) findViewById(R.id.llTitle); 58 59//得到组件对象 60sinaCt= (CheckedTextView)findViewById(R.id.ctvSw); 61qzoneCt= (CheckedTextView)findViewById(R.id.ctvQz); 62tengxunCt = (CheckedTextView)findViewById(R.id.ctvTc); 63renrenCt = (CheckedTextView)findViewById(R.id.ctvRr); 64} 65 66/** 67* 初始化数据 68*/ 69private void initData(){ 70llTitle.getBtnBack().setOnClickListener(new OnClickListener() { 71@Override 72public void onClick(View v) { 73finish(); 74} 75}); 76llTitle.getTvTitle().setText("用户授权登录"); 77 78//设置监听 79sinaCt.setOnClickListener(this); 80qzoneCt.setOnClickListener(this); 81tengxunCt.setOnClickListener(this); 82renrenCt.setOnClickListener(this); 83 84//获取平台列表 85AbstractWeibo[] weibos = AbstractWeibo.getWeiboList(this); 86 87for(int i = 0; i < weibos.length; i++){ 88if (!weibos[i].isValid()) { 89continue; 90} 91 92CheckedTextView ctv = getView(weibos[i]); 93if (ctv != null) { 94ctv.setChecked(true); 95// 得到授权用户的用户名称 96String userName = weibos[i].getDb().get("nickname"); 97if (userName == null || userName.length() < = 0 || "null".equals(userName)) { 98// 如果平台已经授权却没有拿到帐号名称,则自动获取用户资料,以获取名称 99userName = getWeiboName(weibos[i]); 100//添加平台事件监听 101weibos[i].setWeiboActionListener(this); 102//显示用户资料,null表示显示自己的资料 103weibos[i].showUser(null); 104} 105ctv.setText(userName); 106} 107} 108} 109 110/** 111* 在CheckedTextView组件中显示授权用户的名称 112*/ 113private CheckedTextView getView(AbstractWeibo weibo) { 114if (weibo == null) { 115return null; 116} 117 118String name = weibo.getName(); 119if (name == null) { 120return null; 121} 122 123View v = null; 124if (SinaWeibo.NAME.equals(name)) { 125v = findViewById(R.id.ctvSw); 126} 127else if (TencentWeibo.NAME.equals(name)) { 128v = findViewById(R.id.ctvTc); 129} 130else if (Renren.NAME.equals(name)) { 131v = findViewById(R.id.ctvRr); 132} 133else if (QZone.NAME.equals(name)) { 134v = findViewById(R.id.ctvQz); 135} 136 137if (v == null) { 138return null; 139} 140 141if (! (v instanceof CheckedTextView)) { 142return null; 143} 144 145return (CheckedTextView) v; 146} 147 148/** 149* 得到授权用户的用户名称 150*/ 151private String getWeiboName(AbstractWeibo weibo) { 152if (weibo == null) { 153return null; 154} 155 156String name = weibo.getName(); 157if (name == null) { 158return null; 159} 160 161int res = 0; 162if (SinaWeibo.NAME.equals(name)) { 163res = R.string.sinaweibo; 164} 165else if (TencentWeibo.NAME.equals(name)) { 166res = R.string.tencentweibo; 167} 168else if (Renren.NAME.equals(name)) { 169res = R.string.renren; 170} 171else if (QZone.NAME.equals(name)) { 172res = R.string.qzone; 173} 174 175if (res == 0) { 176return name; 177} 178return this.getResources().getString(res); 179} 180 181/** 182* 授权和取消授权的按钮点击监听事件 183*/ 184@Override 185public void onClick(View v) { 186AbstractWeibo weibo = getWeibo(v.getId()); 187 188CheckedTextView ctv = (CheckedTextView) v; 189if (weibo == null) { 190ctv.setChecked(false); 191ctv.setText(R.string.not_yet_authorized); 192return; 193} 194 195if (weibo.isValid()) { 196weibo.removeAccount(); 197ctv.setChecked(false); 198ctv.setText(R.string.not_yet_authorized); 199return; 200} 201 202weibo.setWeiboActionListener(this); 203weibo.showUser(null); 204} 205 206/** 207* 获得授权 208*/ 209private AbstractWeibo getWeibo(int vid) { 210String name = null; 211switch (vid) { 212// 进入新浪微博的授权页面 213case R.id.ctvSw: 214name = SinaWeibo.NAME; 215break; 216// 进入腾讯微博的授权页面 217case R.id.ctvTc: 218name = TencentWeibo.NAME; 219break; 220// 进入人人网的授权页面 221case R.id.ctvRr: 222name = Renren.NAME; 223break; 224// 进入QQ空间的授权页面 225case R.id.ctvQz: 226name = QZone.NAME; 227break; 228} 229 230if (name != null) { 231return AbstractWeibo.getWeibo(this, name); 232} 233return null; 234} 235 236/** 237* 授权成功的回调 238* weibo - 回调的平台 239* action - 操作的类型 240* res - 请求的数据通过res返回 241*/ 242@Override 243public void onComplete(AbstractWeibo weibo, int action,HashMap< String, Object> res) { 244Message msg = new Message(); 245msg.arg1 = 1; 246msg.arg2 = action; 247msg.obj = weibo; 248handler.sendMessage(msg); 249} 250 251/** 252* 授权失败的回调 253*/ 254@Override 255public void onError(AbstractWeibo weibo, int action, Throwable t) { 256t.printStackTrace(); 257 258Message msg = new Message(); 259msg.arg1 = 2; 260msg.arg2 = action; 261msg.obj = weibo; 262handler.sendMessage(msg); 263} 264 265/** 266* 取消授权的回调 267*/ 268@Override 269public void onCancel(AbstractWeibo weibo, int action) { 270Message msg = new Message(); 271msg.arg1 = 3; 272msg.arg2 = action; 273msg.obj = weibo; 274handler.sendMessage(msg); 275} 276 277/** 278* 处理从授权页面返回的结果 279* 280* 如果获取到用户的名称,则显示名称;否则如果已经授权,则显示平台名称 281*/ 282@Override 283public boolean handleMessage(Message msg) { 284AbstractWeibo weibo = (AbstractWeibo) msg.obj; 285String text = MainActivity.actionToString(msg.arg2); 286 287switch (msg.arg1) { 288case 1: { // 成功 289text = weibo.getName() + " completed at " + text; 290Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 291} 292break; 293case 2: { // 失败 294text = weibo.getName() + " caught error at " + text; 295Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 296return false; 297} 298case 3: { // 取消 299text = weibo.getName() + " canceled at " + text; 300Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 301return false; 302} 303} 304 305CheckedTextView ctv = getView(weibo); 306if (ctv != null) { 307ctv.setChecked(true); 308String userName = weibo.getDb().get("nickname"); // getAuthedUserName(); 309if (userName == null || userName.length() < = 0 310|| "null".equals(userName)) { 311userName = getWeiboName(weibo); 312} 313ctv.setText(userName); 314} 315return 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//定义标题栏布局对象 37private TitleLayout llTitle; 38 39private Button sinaBt,renrenBt,qzoneBt,tengxunBt; 40 41private Handler handler; 42 43protected void onCreate(Bundle savedInstanceState) { 44super.onCreate(savedInstanceState); 45 46handler = new Handler(this); 47 48setContentView(R.layout.activity_userinfo); 49 50initView(); 51 52initData(); 53 54} 55 56/** 57* 初始化组件 58*/ 59private void initView(){ 60//得到标题栏对象 61llTitle = (TitleLayout) findViewById(R.id.llTitle); 62 63//得到按钮对象 64sinaBt= (Button) findViewById(R.id.btnSw); 65renrenBt = (Button) findViewById(R.id.btnRr); 66qzoneBt= (Button) findViewById(R.id.btnQz); 67tengxunBt = (Button) findViewById(R.id.btnTc); 68 69 70} 71 72/** 73* 初始化数据 74*/ 75private void initData(){ 76//标题栏设置返回按钮监听 77llTitle.getBtnBack().setOnClickListener(this); 78//设置标题栏的标题文本 79llTitle.getTvTitle().setText(R.string.get_my_info); 80 81//设置监听 82sinaBt.setOnClickListener(this); 83renrenBt.setOnClickListener(this); 84qzoneBt.setOnClickListener(this); 85tengxunBt.setOnClickListener(this); 86} 87 88/** 89* 点击按钮获取授权用户的资料 90*/ 91@Override 92public void onClick(View v) { 93if (v.equals(llTitle.getBtnBack())) { 94finish(); 95return; 96} 97 98String name = null; 99 100switch (v.getId()) { 101case R.id.btnSw: 102name = SinaWeibo.NAME; 103break; 104case R.id.btnTc: 105name = TencentWeibo.NAME; 106break; 107case R.id.btnRr: 108name = Renren.NAME; 109break; 110case R.id.btnQz: 111name = QZone.NAME; 112break; 113} 114 115if (name != null) { 116AbstractWeibo weibo = AbstractWeibo.getWeibo(this, name); 117weibo.setWeiboActionListener(this); 118String account = null; 119 120weibo.showUser(account); 121} 122} 123 124public void onComplete(AbstractWeibo weibo, int action,HashMap< String, Object> res) { 125Message msg = new Message(); 126msg.arg1 = 1; 127msg.arg2 = action; 128msg.obj = weibo; 129handler.sendMessage(msg); 130 131Message msg2 = new Message(); 132msg2.what = 1; 133JsonUtils ju = new JsonUtils(); 134String json = ju.fromHashMap(res); 135msg2.obj = ju.format(json); 136handler.sendMessage(msg2); 137} 138 139public void onError(AbstractWeibo weibo, int action, Throwable t) { 140t.printStackTrace(); 141 142Message msg = new Message(); 143msg.arg1 = 2; 144msg.arg2 = action; 145msg.obj = weibo; 146handler.sendMessage(msg); 147} 148 149public void onCancel(AbstractWeibo weibo, int action) { 150Message msg = new Message(); 151msg.arg1 = 3; 152msg.arg2 = action; 153msg.obj = weibo; 154handler.sendMessage(msg); 155} 156 157/** 处理操作结果 */ 158public boolean handleMessage(Message msg) { 159switch(msg.what) { 160case 1: { 161Intent i = new Intent(this, ShowInforActivity.class); 162i.putExtra("data", String.valueOf(msg.obj)); 163startActivity(i); 164} 165break; 166default: { 167AbstractWeibo weibo = (AbstractWeibo) msg.obj; 168String text = MainActivity.actionToString(msg.arg2); 169switch (msg.arg1) { 170case 1: { // 成功 171text = weibo.getName() + " completed at " + text; 172} 173break; 174case 2: { // 失败 175text = weibo.getName() + " caught error at " + text; 176} 177break; 178case 3: { // 取消 179text = weibo.getName() + " canceled at " + text; 180} 181break; 182} 183 184Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 185} 186break; 187} 188return 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 { 17private TitleLayout llTitle; 18 19protected void onCreate(Bundle savedInstanceState) { 20super.onCreate(savedInstanceState); 21setContentView(R.layout.activity_show_userinfo); 22 23llTitle = (TitleLayout) findViewById(R.id.llTitle); 24llTitle.getBtnBack().setOnClickListener(this); 25llTitle.getTvTitle().setText("用户资料"); 26 27TextView tvJson = (TextView) findViewById(R.id.tvJson); 28tvJson.setText(getIntent().getStringExtra("data")); 29} 30 31@Override 32public void onClick(View v) { 33if (v.equals(llTitle.getBtnBack())) { 34finish(); 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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/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(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
推荐阅读
- Win8电脑系统组件被删除无法联网怎样办
- Android 4.0 Launcher2源码分析——主布局文件(转)
- web测试和app测试
- android kl 文件的作用
- 202. Happy Number
- appium-FAQ(持续更新...)
- Appium常见API 一
- Android studio 自定义打包apk名
- android sdk那些不得不说的事儿~~~