android 第三方登录

Android开发实现微博三方登录(1)


本文讲述三种实现微博三方登录的接口方法,其实说是三种,但他们只有一个微小的区别,就是进入授权页面前调用的方法名不同而已


1.  SSO单点登录方式授权,调用这种方法只能在你手机安装了新浪微博APP的前提下才能实现

2. Web页面登录方式授权,这种方法会跳出一个微博登录的Web页面,从而实现登录

3. all in one方式授权,此种授权方式会根据手机是否安装微博客户端来决定使用sso授权还是网页授权,如果安装有微博客户端 则调用微博客户端授权,否则调用Web页面方式授权


下面是具体实现的流程:


一、授权部分(在代码中获取到一个Oauth2AccessToken对象)


1.上新浪微博开放平台申请APP key 和App secret    ,具体步骤省略,无非就是填写一些应用程序的信息,还是非常容易的申请到的(未注册新浪的开发者账号可能需要先注册一个账号),下面是申请成功后的界面

http://open.weibo.com/



2.在上面的界面中“基本信息”目录下填写Android 包名(你项目的包名)、Android签名(需要下载签名工具生成项目对应的签名)等信息,然后点击保存



然后在“高级信息”下添加回调页(http://api.weibo.com/oauth2/default.html),然后点击提交



如果运行测试的时候,登录的账号不是注册应用的账号,那么还需要在“测试信息”下添加测试账号,然后点击保存



3.下载SDK   地址:http://open.weibo.com/wiki/SDK


4.在工程的main文件夹下新建一个jniLibs文件夹(不要拼错),将SDK中libs文件夹下的所有文件夹全部拷到工程中jnilib目录下。再将weiboSDKCore_3.1.4.jar包引入到工程中。


5.添加权限

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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" />  


6.新建一个Constants类。(其中的APP_KEY替换成自己的APP key,另外细心的人可能会发现,上面我们添加的授权回调页就是这里的REDIRECT_URL)
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 该类定义了微博授权时所需要的参数。 
  3.  *  
  4.  * @author SINA 
  5.  * @since 2013-09-29 
  6.  */  
  7. public class Constants {  
  8.   
  9.     /** 当前 DEMO 应用的 APP_KEY,第三方应用应该使用自己的 APP_KEY 替换该 APP_KEY */  
  10.     public static final String APP_KEY      = "78219253";  
  11.   
  12.     /**  
  13.      * 当前 DEMO 应用的回调页,第三方应用可以使用自己的回调页。 
  14.      *  
  15.      * <p> 
  16.      * 注:关于授权回调页对移动客户端应用来说对用户是不可见的,所以定义为何种形式都将不影响, 
  17.      * 但是没有定义将无法使用 SDK 认证登录。 
  18.      * 建议使用默认回调页:https://api.weibo.com/oauth2/default.html 
  19.      * </p> 
  20.      */  
  21.     public static final String REDIRECT_URL = "http://api.weibo.com/oauth2/default.html";  
  22.   
  23.     /** 
  24.      * Scope 是 OAuth2.0 授权机制中 authorize 接口的一个参数。通过 Scope,平台将开放更多的微博 
  25.      * 核心功能给开发者,同时也加强用户隐私保护,提升了用户体验,用户在新 OAuth2.0 授权页中有权利 
  26.      * 选择赋予应用的功能。 
  27.      *  
  28.      * 我们通过新浪微博开放平台-->管理中心-->我的应用-->接口管理处,能看到我们目前已有哪些接口的 
  29.      * 使用权限,高级权限需要进行申请。 
  30.      *  
  31.      * 目前 Scope 支持传入多个 Scope 权限,用逗号分隔。 
  32.      *  
  33.      * 有关哪些 OpenAPI 需要权限申请,请查看:http://open.weibo.com/wiki/%E5%BE%AE%E5%8D%9AAPI 
  34.      * 关于 Scope 概念及注意事项,请查看:http://open.weibo.com/wiki/Scope 
  35.      */  
  36.     public static final String SCOPE =   
  37.             "email,direct_messages_read,direct_messages_write,"  
  38.             + "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"  
  39.             + "follow_app_official_microblog," + "invitation_write";  
  40. }  


7.Java代码中需要三个对象

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 注意:SsoHandler 仅当 SDK 支持 SSO 时有效 
  3.      */  
  4.     private SsoHandler mSsoHandler;  
  5.   
  6.     private AuthInfo mAuthInfo;  
  7.   
  8.     /** 
  9.      * 封装了 "access_token","expires_in","refresh_token",并提供了他们的管理功能,用于在回调方法中接收授权成功后返回的信息 
  10.      */  
  11.     private Oauth2AccessToken mAccessToken;  

初始化对象

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. // 快速授权时,请不要传入 SCOPE,否则可能会授权不成功  
  2.         mAuthInfo = new AuthInfo(this, Constants.APP_KEY, Constants.REDIRECT_URL, Constants.SCOPE);  
  3.         mSsoHandler = new SsoHandler(this, mAuthInfo);  

8.定义一个WeiBoAuthListener的实现类,不管是上面提到的哪一种授权方式,都会需要这个实现类

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 微博认证授权回调类。 
  3.      * 1. SSO 授权时,需要在 {@link #onActivityResult} 中调用 {@link SsoHandler#authorizeCallBack} 后, 
  4.      * 该回调才会被执行。 
  5.      * 2. 非 SSO 授权时,当授权结束后,该回调就会被执行。 
  6.      * 当授权成功后,请保存该 access_token、expires_in、uid 等信息到 SharedPreferences 中。 
  7.      */  
  8.     class AuthListener implements WeiboAuthListener {  
  9.   
  10.         @Override  
  11.         public void onComplete(Bundle bundle) {  
  12. //            System.out.println("onComplete(Bundle values)  ------>  "  
  13. //                    + bundle.toString());  
  14.             // onComplete(Bundle values) ------>  
  15.             // Bundle[ {_weibo_transaction = 1469413517894,  
  16.             // access_token = 2.00a64JBGyY87OCfa7707a82fzincGB,  
  17.             // refresh_token = 2.00a64JBGyY87OC11c02519480EWT1g,  
  18.             // expires_in = 2651682,  
  19.             // _weibo_appPackage = com.sina.weibo,  
  20.             // com.sina.weibo.intent.extra.NICK_NAME = 用户5513808278,  
  21.             // userName = 用户5513808278,  
  22.             // uid = 5513808278,  
  23.             // com.sina.weibo.intent.extra.USER_ICON = null} ]  
  24.   
  25.   
  26.             //从Bundle中解析Token  
  27.             mAccessToken = Oauth2AccessToken.parseAccessToken(bundle);  
  28. //            System.out.println("onComplete  mAccessToken  ------>  "  
  29. //                    + mAccessToken.toString());  
  30.             // onComplete mAccessToken ------>  
  31.             // uid: 5513808278,  
  32.             // access_token: 2.00a64JBGyY87OCfa7707a82fzincGB,  
  33.             // refresh_token: 2.00a64JBGyY87OC11c02519480EWT1g,  
  34.             // phone_num: ,  
  35.             // expires_in: 1472065200534  
  36.   
  37.             if (mAccessToken.isSessionValid()) {//授权成功  
  38.                 Toast.makeText(MainActivity.this"登陆成功", Toast.LENGTH_SHORT).show();  
  39.                 //显示Access_Token  
  40.                 tvAccessToken.setText("Access_token:\n" + mAccessToken.getToken());  
  41.                 //获取用户具体信息  
  42. //                getUserInfo();  
  43.             } else {  
  44.                 /** 
  45.                  *  以下几种情况,您会收到 Code: 
  46.                  * 1. 当您未在平台上注册应用程序的包名与签名时; 
  47.                  * 2. 当您注册的应用程序包名与签名不正确时; 
  48.                  * 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。 
  49.                  */  
  50.                 String code = bundle.getString("code");//直接从bundle里边获取  
  51.                 if (!TextUtils.isEmpty(code)) {  
  52.                     Toast.makeText(MainActivity.this"签名不正确", Toast.LENGTH_SHORT).show();  
  53.                 }  
  54.             }  
  55. //            String phoneNum = mAccessToken.getPhoneNum();//通过手机短信授权登录时可以拿到,此demo未实现此种授权方式  
  56.         }  
  57.   
  58.         @Override  
  59.         public void onWeiboException(WeiboException e) {  
  60.             Toast.makeText(MainActivity.this"授权异常", Toast.LENGTH_SHORT).show();  
  61.         }  
  62.   
  63.         @Override  
  64.         public void onCancel() {  
  65.             Toast.makeText(MainActivity.this"授权取消", Toast.LENGTH_SHORT).show();  
  66.         }  
  67.     }  

9.下面是各种授权方式调用的方法(可以看到,三种登录方式主要的不同就表现在这——ssohandler对象调用方法不同)

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * all in one 方式授权,自动检测 
  3.      */  
  4.         mSsoHandler.authorize(new AuthListener());  
  5.       
  6.   
  7.     /** 
  8.      * Web授权 
  9.      */  
  10.       
  11.         mSsoHandler.authorizeWeb(new AuthListener());  
  12.       
  13.   
  14.     /** 
  15.      * SSO授权,仅客户端 
  16.      */  
  17.       
  18.         mSsoHandler.authorizeClientSso(new AuthListener());  
  19.         

注意:如果是使用web授权,则需要在AndroidManifest.xml中申明以下Activity

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <!--微博Web授权时,需要注册授权界面-->  
  2.         <activity  
  3.             android:name="com.sina.weibo.sdk.component.WeiboSdkBrowser"  
  4.             android:configChanges="keyboardHidden|orientation"  
  5.             android:exported="false"  
  6.             android:windowSoftInputMode="adjustResize"></activity>  

10.很容易落下的一步,重写onActivityResult方法,否则调不到回调方法

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.         super.onActivityResult(requestCode, resultCode, data);  
  4.   
  5.         //SSO 授权回调  
  6.         //重要:发起sso登录的activity必须重写onActivtyResults  
  7.         if (mSsoHandler != null) {  
  8.             mSsoHandler.authorizeCallBack(requestCode, resultCode, data);  
  9.         }  
  10.     }  

如此,授权部分便全部实现了


二、获取用户的基本信息(通过上面获取到的Oauth2AccessToken对象获取用户基本信息)


11.要获取信息,应该需要将SDK中的weibosdk作为库引入到工程中(我直接引了它的jar包,经验证可以实现)。


先声明一个变量

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. //获取用户信息的接口(需要先把官方提供的weibosdk库引入到工程当中来)  
  2.     private UsersAPI mUsersAPI;  

然后在上面weiboAuthListener的onComplete回调方法中将getUserInfo();那句代码的注释去掉。getUserInfo()方法的实现如下。

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * 获取用户个人信息 
  3.      */  
  4.     private void getUserInfo() {  
  5.         //获取用户信息接口  
  6.         mUsersAPI = new UsersAPI(MainActivity.this, Constants.APP_KEY, mAccessToken);  
  7.         System.out.println("mUsersAPI  ----->   " + mUsersAPI.toString());  
  8.   
  9.         //调用接口  
  10.         long uid = Long.parseLong(mAccessToken.getUid());  
  11.         System.out.println("--------------uid-------------->    " + uid);  
  12.         mUsersAPI.show(uid, mListener);//将uid传递到listener中,通过uid在listener回调中接收到该用户的json格式的个人信息  
  13.     }  
  14.     /** 
  15.      * 实现异步请求接口回调,并在回调中直接解析User信息 
  16.      */  
  17.     private RequestListener mListener = new RequestListener() {  
  18.         @Override  
  19.         public void onComplete(String response) {  
  20.             if (!TextUtils.isEmpty(response)) {  
  21.                 //调用User#parse将JSON串解析成User对象  
  22.                 User user = User.parse(response);  
  23.                 String nickName = user.screen_name;  
  24.                 tvNickName.setText("用户昵称: " + user.screen_name);  
  25.                 tvGender.setText("用户性别: " + user.gender);  
  26.                 tvLocation.setText("用户所在地: " + user.location);  
  27. //                Toast.makeText(LogInActivity.this, "用户的昵称: " + nickName, Toast.LENGTH_SHORT).show();  
  28.             }  
  29.         }  
  30.   
  31.         /** 
  32.          *如果运行测试的时候,登录的账号不是注册应用的账号,那么需要去: 
  33.          *开放平台-》管理中心-》应用信息-》测试信息-》添加测试账号(填写用户昵称)! 
  34.          * 否则便会抛出以下异常 
  35.          */  
  36.         @Override  
  37.         public void onWeiboException(WeiboException e) {  
  38.             e.printStackTrace();  
  39.             Toast.makeText(MainActivity.this"获取用户个人信息 出现异常", Toast.LENGTH_SHORT).show();  
  40.         }  
  41.     };  

这样就可以获取到用户的基本信息了!

User类中的各项信息可参考: http://open.weibo.com/wiki/2/users/show

本demo参照SDK中“新文档”文件夹下的Word文档6.1、7.1完成。

Demo下载地址:http://download.csdn.net/detail/highboys/9597488


Android开发实现微博三方登录(2)


做过新浪微博第三方登录的朋友都清楚,他们的官方文档写的真心糟糕,添加新应用也很麻烦。我也是一边看文档,一边看demo,摸爬滚打才实现第三方登录的功能。今天和大家分享一个完整的开发流程,从申请开发者账号,到集成SDK,到代码编写。ps:我所使用的是SDK版本是weiboSDKCore_3.1.2

第一步:申请开发者账号,官网http://open.weibo.com

登录或注册新浪微博账号

然后创建新应用,创建的时候要注意几点:

拿到APPID,我的应用->应用信息->基本信息

我的应用->应用信息->基本信息

包名是指AndroidManifest.xml文件里面package属性对应的内容

签名必须通过官方提供的MD5签名工具生成,可百度搜索,我这里也有链接http://pan.baidu.com/s/1qWlD1LE

大概长这个样儿,对照着签名填写到官网的Android签名那栏就好。

点击我的应用->应用信息->高级信息,填写回调地址,这个是授权成功后调用的地址,后续再代码编写的时候会用到,必须保持一致,可以使用http://www.sina.com

添加测试账号,

第二步:集成SDK,

到官网下载最新的SDK文件,

或者用我这里提供的

http://pan.baidu.com/s/1sjFxEbz

把目录weibo_android_sdk-master\libs下的6个文件夹拷贝到工程的libs文件中,

weibo_android_sdk-master目录下的weiboSDKCore_3.1.2.jar复制到libs文件中

然后再选中weiboSDKCore_3.1.2.jar右键Build Path->Add to Build Path

至此集成已经成功一半

修改AndroidManifest.xml文件,添加以下代码

 <activity
            android:name="com.sina.weibo.sdk.component.WeiboSdkBrowser"
            android:configChanges="keyboardHidden|orientation"
            android:exported="false"
            android:windowSoftInputMode="adjustResize" >
        </activity>

        <service
            android:name="com.sina.weibo.sdk.net.DownloadService"
            android:exported="false" >
        </service>

添加权限:

<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

这样SDK算是集成完毕了

第三步:代码编写

我主要是参考官方demo来写的,关键是三个java文件

LoginActivity,集中调用新浪微博API的类,实现了第三方授权,登录,退出,登录时显示用户信息的功能

package com.example.thirdpartyloginafc;

import java.text.SimpleDateFormat;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.sina.weibo.sdk.auth.AuthInfo;
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
import com.sina.weibo.sdk.auth.WeiboAuthListener;
import com.sina.weibo.sdk.auth.sso.SsoHandler;
import com.sina.weibo.sdk.exception.WeiboException;

public class LoginActivity extends Activity implements OnClickListener {

	private AuthInfo mAuthInfo;
	private Button btnweibo;
	private Button btnlogout;
	private TextView tv;
	private String nickname="";

	/** 封装了 "access_token","expires_in","refresh_token",并提供了他们的管理功能 */
	private Oauth2AccessToken mAccessToken;

	/** 注意:SsoHandler 仅当 SDK 支持 SSO 时有效 */
	private SsoHandler mSsoHandler;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initweibologin();
		initViews();
		initEvents();
		initData();
	}

	private void initData() {
		// TODO Auto-generated method stub
		// 从 SharedPreferences 中读取上次已保存好 AccessToken 等信息,
		// 第一次启动本应用,AccessToken 不可用
		mAccessToken = AccessTokenKeeper.readAccessToken(this);
		if (mAccessToken.isSessionValid()) {
			updateTokenView(true);
		}
	}

	private void initViews() {

		btnweibo = (Button) findViewById(R.id.btn_weibo_login);
		btnlogout = (Button) findViewById(R.id.btnlogout);
		tv = (TextView) findViewById(R.id.content);
		// 获取 Token View,并让提示 View 的内容可滚动(小屏幕可能显示不全)
		tv.setMovementMethod(new ScrollingMovementMethod());
	}

	private void initEvents() {
		btnweibo.setOnClickListener(this);
		btnlogout.setOnClickListener(this);

	}

	/**
	 * 进行微博授权初始化操作
	 */
	private void initweibologin() {
		// TODO Auto-generated method stub
		// 初始化授权类对象,将应用的信息保存
		mAuthInfo = new AuthInfo(this, Constants.APP_KEY,
				Constants.REDIRECT_URL, Constants.SCOPE);
		mSsoHandler = new SsoHandler(LoginActivity.this, mAuthInfo);

	}

	/**
	 * 当 SSO 授权 Activity 退出时,该函数被调用。
	 * 
	 * @see {@link Activity#onActivityResult}
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		// SSO 授权回调
		// 重要:发起 SSO 登陆的 Activity 必须重写 onActivityResults
		if (mSsoHandler != null) {
			mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
		}

	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.btn_weibo_login:// SSO 授权, ALL IN ONE
									// 如果手机安装了微博客户端则使用客户端授权,没有则进行网页授权
			mSsoHandler.authorize(new AuthListener());
			break;

		case R.id.btnlogout:// 用户登出
			nickname = "";
			AccessTokenKeeper.clear(getApplicationContext());
			mAccessToken = new Oauth2AccessToken();
			updateTokenView(false);
			break;
		default:
			break;
		}
	}

	/**
	 * 微博认证授权回调类。 1. SSO 授权时,需要在 {@link #onActivityResult} 中调用
	 * {@link SsoHandler#authorizeCallBack} 后, 该回调才会被执行。 2. 非 SSO
	 * 授权时,当授权结束后,该回调就会被执行。 当授权成功后,请保存该 access_token、expires_in、uid 等信息到
	 * SharedPreferences 中。
	 */
	class AuthListener implements WeiboAuthListener {

		@Override
		public void onCancel() {
			// TODO Auto-generated method stub
			Toast.makeText(LoginActivity.this"取消授权", Toast.LENGTH_LONG)
					.show();
		}

		@Override
		public void onComplete(Bundle values) {
			// TODO Auto-generated method stub
			// 从 Bundle 中解析 Token
			mAccessToken = Oauth2AccessToken.parseAccessToken(values);
			if (mAccessToken.isSessionValid()) {
				nickname = "用户名:"
						+ String.valueOf(values
								.get("com.sina.weibo.intent.extra.NICK_NAME"));
				// 显示 Token
				updateTokenView(false);

				// 保存 Token 到 SharedPreferences
				AccessTokenKeeper.writeAccessToken(LoginActivity.this,
						mAccessToken);
				Toast.makeText(LoginActivity.this"授权成功", Toast.LENGTH_SHORT)
						.show();
				// Toast.makeText(
				// LoginActivity.this,
				// "头像地址:"
				// + String.valueOf(values
				// .get("com.sina.weibo.intent.extra.USER_ICON")),
				// Toast.LENGTH_LONG).show();

				Toast.makeText(LoginActivity.this, nickname, Toast.LENGTH_LONG)
						.show();

			} else {
				// 以下几种情况,您会收到 Code:
				// 1. 当您未在平台上注册的应用程序的包名与签名时;
				// 2. 当您注册的应用程序包名与签名不正确时;
				// 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。
				String code = values.getString("code");
				String message = "授权失败";
				if (!TextUtils.isEmpty(code)) {
					message = message + "\nObtained the code: " + code;
				}
				Toast.makeText(LoginActivity.this, message, Toast.LENGTH_LONG)
						.show();
			}
		}

		@Override
		public void onWeiboException(WeiboException e) {
			// TODO Auto-generated method stub
			Toast.makeText(LoginActivity.this,
					"Auth exception : " + e.getMessage(), Toast.LENGTH_LONG)
					.show();
		}

	}

	/**
	 * 显示当前 Token 信息。
	 * 
	 * @param hasExisted
	 *            配置文件中是否已存在 token 信息并且合法
	 */
	private void updateTokenView(boolean hasExisted) {
		String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
				.format(new java.util.Date(mAccessToken.getExpiresTime()));
		String format = getString(R.string.weibosdk_demo_token_to_string_format_1);
		tv.setText(String.format(format, mAccessToken.getToken(), date));

		String message = String.format(format, mAccessToken.getToken(), date);
		if (hasExisted) {
			message = getString(R.string.weibosdk_demo_token_has_existed)
					+ "\n" + message;

		}
		message += "\n" + nickname;
		tv.setText(message);
	}

}

package com.example.thirdpartyloginafc;

/*
 * Copyright (C) 2010-2013 The SINA WEIBO Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

import com.sina.weibo.sdk.auth.Oauth2AccessToken;

/**
 * 该类定义了微博授权时所需要的参数。
 * 
 * @author SINA
 * @since 2013-10-07
 */
public class AccessTokenKeeper {
	private static final String PREFERENCES_NAME = "com_weibo_sdk_android";

	private static final String KEY_UID = "uid";
	private static final String KEY_ACCESS_TOKEN = "access_token";
	private static final String KEY_EXPIRES_IN = "expires_in";
	private static final String KEY_REFRESH_TOKEN = "refresh_token";
	

	/**
	 * 保存 Token 对象到 SharedPreferences。
	 * 
	 * @param context
	 *            应用程序上下文环境
	 * @param token
	 *            Token 对象
	 */
	public static void writeAccessToken(Context context, Oauth2AccessToken token) {
		if (null == context || null == token) {
			return;
		}

		SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME,
				Context.MODE_APPEND);
		Editor editor = pref.edit();
		editor.putString(KEY_UID, token.getUid());
		editor.putString(KEY_ACCESS_TOKEN, token.getToken());
		editor.putString(KEY_REFRESH_TOKEN, token.getRefreshToken());
		editor.putLong(KEY_EXPIRES_IN, token.getExpiresTime());
		
		editor.commit();
	}

	/**
	 * 从 SharedPreferences 读取 Token 信息。
	 * 
	 * @param context
	 *            应用程序上下文环境
	 * 
	 * @return 返回 Token 对象
	 */
	public static Oauth2AccessToken readAccessToken(Context context) {
		if (null == context) {
			return null;
		}

		Oauth2AccessToken token = new Oauth2AccessToken();
		SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME,
				Context.MODE_APPEND);
		token.setUid(pref.getString(KEY_UID, ""));
		token.setToken(pref.getString(KEY_ACCESS_TOKEN, ""));
		token.setRefreshToken(pref.getString(KEY_REFRESH_TOKEN, ""));
		token.setExpiresTime(pref.getLong(KEY_EXPIRES_IN, 0));

		return token;
	}

	/**
	 * 清空 SharedPreferences 中 Token信息。
	 * 
	 * @param context
	 *            应用程序上下文环境
	 */
	public static void clear(Context context) {
		if (null == context) {
			return;
		}

		SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME,
				Context.MODE_APPEND);
		Editor editor = pref.edit();
		editor.clear();
		editor.commit();
	}
}

package com.example.thirdpartyloginafc;

public class Constants {
	public static final String APP_KEY = "自己的id";
	public static final String REDIRECT_URL = "与网页对应的回调地址;
	public static final String SCOPE = "email,direct_messages_read,direct_messages_write,"
			+ "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
			+ "follow_app_official_microblog," + "invitation_write";

}

运行结果

授权成功

官方开放了三种登录方式,第一种是通过客户端登录,第二种是通过web登录,第三种是先尝试通过客户端登录,如果没有安装客户端,就通过web登录,这里使用的是第三种方式

本例子的代码:http://pan.baidu.com/s/1nttlgt7

导入工程之后,记得修改Constants里面的APP_KEY和REDIRECT_URL,有问题欢迎交流!!

微博开发sdk 及开发帮助文档的地址


https://github.com/sinaweibosdk/weibo_android_sdk



Android实现QQ第三方登录


Android 实现QQ第三方登录

在项目中需要实现QQ第三方登录,经过一番努力算是写出来了,现在总结以下,以防以后遗忘,能帮到其他童鞋就更好了。

首先肯定是去下载SDK和DEMO

http://wiki.open.qq.com/wiki/mobile/SDK下载

本文是我自己整合后的简单DEMO。

先看下效果图吧

\\\\\

原理:我们要使用QQ登录我们的应用,不是不用注册,是我们在后台为用户注册了,但是用户不知道,注册需要唯一标识,上图的那串字母与数字的组合就是我们要获得的唯一标识:OpenID.

跟着代码来说吧。

首先,我们要加载open_sdk.jar和mta-sdk-1.00.jar这两个架包顺便看下我总共用到的类

\\

其中,AppConstant中是用来放置APPID的,由于考虑到还可能引入其他第三方登录,为方便管理,故创建此类。Util是根据路径从网上获取图片的处理类

 

好了进入主题

首先在AndroidManifest.xml中进行两个定义如果不定义是不行的

01. <activity
02. android:name="com.tencent.tauth.AuthActivity"
03. android:launchMode="singleTask"
04. android:noHistory="true" >
05. <intent-filter>
06. <action android:name="android.intent.action.VIEW" />
07.  
08. <category android:name="android.intent.category.DEFAULT" />
09. <category android:name="android.intent.category.BROWSABLE" />
10.  
11. <data android:scheme="tencent222222" /><!—注意在这里用你的appid替换222222 -->
12. </intent-filter>
13. </activity>
14. <activity android:name="com.tencent.connect.common.AssistActivity"
15. android:theme="@android:style/Theme.Translucent.NoTitleBar"
16. android:screenOrientation="portrait"/>

 

然后是两个权限

1. <uses-permission android:name="android.permission.INTERNET" />
2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

 

接下来是布局文件,activity_main.xml登录按钮,获取头像、昵称、openid的textview

01. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03. android:layout_width="fill_parent"
04. android:layout_height="fill_parent"
05. android:orientation="vertical">
06. <Button
07. android:id="@+id/login"
08. android:layout_width="fill_parent"
09. android:layout_height="wrap_content"
10. android:text="登录"/>
11. <ImageView
12. android:id="@+id/user_logo"
13. android:layout_width="wrap_content"
14. android:layout_height="wrap_content"
15. />
16. <TextView
17. android:id="@+id/user_nickname"
18. android:layout_width="wrap_content"
19. android:layout_height="wrap_content"
20. android:textColor="#80505050"
21. android:textSize="18sp"
22. />
23. <TextView
24. android:id="@+id/user_openid"
25. android:layout_width="wrap_content"
26. android:layout_height="wrap_content" 
27. />
28.  
29. </LinearLayout>

 

然后是MainActivity

01. public class MainActivity extends Activity implements OnClickListener {
02. TextView openidTextView;
03. TextView nicknameTextView;
04. Button loginButton;
05. ImageView userlogo;
06. private Tencent mTencent;
07. public static QQAuth mQQAuth;
08. public static String mAppid;
09. public static String openidString;
10. public static String nicknameString;
11. public static String TAG="MainActivity";
12. Bitmap bitmap = null;
13. @Override
14. public void onCreate(Bundle savedInstanceState) {
15. super.onCreate(savedInstanceState);
16. setContentView(R.layout.activity_main);
17. //用来登录的Button
18. loginButton=(Button)findViewById(R.id.login);
19. loginButton.setOnClickListener(this);
20. //用来显示OpenID的textView
21. openidTextView=(TextView)findViewById(R.id.user_openid);
22. //用来显示昵称的textview
23. nicknameTextView=(TextView)findViewById(R.id.user_nickname);
24. //用来显示头像的Imageview
25. userlogo=(ImageView)findViewById(R.id.user_logo);
26.  
27. }
28. public void onClick(View v) {
29. // TODO Auto-generated method stub
30. switch (v.getId()) {
31. case R.id.login:
32. LoginQQ();
33. break;
34.  
35. default:
36. break;
37. }
38. }
39. //这里是调用QQ登录的关键代码
40. public void LoginQQ() {
41. //这里的APP_ID请换成你应用申请的APP_ID,我这里使用的是DEMO中官方提供的测试APP_ID 222222
42. mAppid = AppConstant.APP_ID;
43. //第一个参数就是上面所说的申请的APPID,第二个是全局的Context上下文,这句话实现了调用QQ登录
44. mTencent = Tencent.createInstance(mAppid,getApplicationContext());
45. /**通过这句代码,SDK实现了QQ的登录,这个方法有三个参数,第一个参数是context上下文,第二个参数SCOPO 是一个String类型的字符串,表示一些权限
46. 官方文档中的说明:应用需要获得哪些API的权限,由“,”分隔。例如:SCOPE = “get_user_info,add_t”;所有权限用“all” 
47. 第三个参数,是一个事件监听器,IUiListener接口的实例,这里用的是该接口的实现类 */
48. mTencent.login(MainActivity.this,"all"new BaseUiListener());
49.  
50. }
51. /**当自定义的监听器实现IUiListener接口后,必须要实现接口的三个方法,
52. * onComplete  onCancel onError
53. *分别表示第三方登录成功,取消 ,错误。*/
54. private class BaseUiListener implements IUiListener {
55.  
56. public void onCancel() {
57. // TODO Auto-generated method stub
58.  
59. }
60. public void onComplete(Object response) {
61. // TODO Auto-generated method stub
62. Toast.makeText(getApplicationContext(), "登录成功"0).show();
63. try {
64. //获得的数据是JSON格式的,获得你想获得的内容
65. //如果你不知道你能获得什么,看一下下面的LOG
66. Log.e(TAG, "-------------"+response.toString());
67. openidString = ((JSONObject) response).getString("openid");
68. openidTextView.setText(openidString);
69. Log.e(TAG, "-------------"+openidString);
70. //access_token= ((JSONObject) response).getString("access_token");              //expires_in = ((JSONObject) response).getString("expires_in");
71. catch (JSONException e) {
72. // TODO Auto-generated catch block
73. e.printStackTrace();
74. }
75. /**到此已经获得OpneID以及其他你想获得的内容了
76. QQ登录成功了,我们还想获取一些QQ的基本信息,比如昵称,头像什么的,这个时候怎么办?
77. sdk给我们提供了一个类UserInfo,这个类中封装了QQ用户的一些信息,我么可以通过这个类拿到这些信息
78. 如何得到这个UserInfo类呢?  */
79. Q<a href="http://www.it165.net/pro/pkqt/" target="_blank" class="keylink">QT</a>oken qqToken = mTencent.getQ<a href="http://www.it165.net/pro/pkqt/"target="_blank" class="keylink">QT</a>oken();
80. UserInfo info = new UserInfo(getApplicationContext(), <a href="http://www.it165.net/qq/" target="_blank" class="keylink">qq</a>Token);
81. //这样我们就拿到这个类了,之后的操作就跟上面的一样了,同样是解析JSON          
01. info.getUserInfo(new IUiListener() {
02.  
03. public void onComplete(final Object response) {
04. // TODO Auto-generated method stub
05. Log.e(TAG, "---------------111111");
06. Message msg = new Message();
07. msg.obj = response;
08. msg.what = 0;
09. mHandler.sendMessage(msg);
10. Log.e(TAG, "-----111---"+response.toString());
11. /**由于图片需要下载所以这里使用了线程,如果是想获得其他文字信息直接
12. * 在mHandler里进行操作
13. *
14. */
15. new Thread(){
16.  
17. @Override
18. public void run() {
19. // TODO Auto-generated method stub
20. JSONObject json = (JSONObject)response;
21. try {
22. bitmap = Util.getbitmap(json.getString("figureurl_<a href="http://www.it165.net/qq/" target="_blank" class="keylink">qq</a>_2"));
23. catch (JSONException e) {
24. // TODO Auto-generated catch block
25. e.printStackTrace();
26. }
27. Message msg = new Message();
28. msg.obj = bitmap;
29. msg.what = 1;
30. mHandler.sendMessage(msg);
31. }                      
32. }.start();
33. }              
34. public void onCancel() {
35. Log.e(TAG, "--------------111112");
36. // TODO Auto-generated method stub                 
37. }
38. public void onError(UiError arg0) {
39. // TODO Auto-generated method stub
40. Log.e(TAG, "-111113"+":"+arg0);
41. }
42.  
43. });
44.  
45. }
46.  
47. public void onError(UiError arg0) {
48. // TODO Auto-generated method stub
49.  
50. }          
51.  
52. }
53. Handler mHandler = new Handler() {
54.  
55. @Override
56. public void handleMessage(Message msg) {
57. if (msg.what == 0) {
58. JSONObject response = (JSONObject) msg.obj;
59. if (response.has("nickname")) {
60. try {
61. nicknameString=response.getString("nickname");
62.  
63. nicknameTextView.setText(nicknameString);
64. Log.e(TAG, "--"+nicknameString);
65. catch (JSONException e) {
66. // TODO Auto-generated catch block
67. e.printStackTrace();
68. }
69. }
70. }else if(msg.what == 1){
71. Bitmap bitmap = (Bitmap)msg.obj;
72. userlogo.setImageBitmap(bitmap);
73.  
74. }
75. }
76.  
77. };
78.  
79.  
80. }

\

上图是登录Q的返回LOG

\

上图是我们获得腾讯提供的UserInfo返回的LOG

然后是AppConstant.Java

1. public class AppConstant {
2. public static String APP_ID="222222";
3. }

然后是Util.java

01. public class Util {
02. public static String TAG="UTIL";
03. public static Bitmap getbitmap(String imageUri) {
04. Log.v(TAG, "getbitmap:" + imageUri);
05. // 显示网络上的图片
06. Bitmap bitmap = null;
07. try {
08. URL myFileUrl = new URL(imageUri);
09. HttpURLConnection conn = (HttpURLConnection) myFileUrl
10. .openConnection();
11. conn.setDoInput(true);
12. conn.connect();
13. InputStream is = conn.getInputStream();
14. bitmap = BitmapFactory.decodeStream(is);
15. is.close();
16.  
17. Log.v(TAG, "image download finished." + imageUri);
18. catch (IOException e) {
19. e.printStackTrace();
20. Log.v(TAG, "getbitmap bmp fail---");
21. return null;
22. }
23. return bitmap;
24. }
25. }

 

至此全部代码就在这里了,我们获得了OpenID这个唯一标识最关键的东西,然后看项目中需要登录的接口还需要什么信息,获取到就能实现登陆了。


qq 官方文档参考


http://wiki.open.qq.com/wiki/创建并配置工程

http://wiki.open.qq.com/wiki/创建实例并实现回调

http://wiki.open.qq.com/wiki/QQ登录和注销

http://wiki.open.qq.com/wiki/mobile/ SDK下载地址



Android 微信第三方登录


这两天,解决了微信第三方授权登录的问题,作为一个新手,想想也是一把辛酸泪。我想着,就把我的遇到的坑给大家分享一下,避免新手遇到我这样的问题能够顺利避开。

步骤一 微信开发者平台

我开始的解决思路是,去微信开发者平台看API文档。

这个API文档的主要意思呢,有三点:

1、你得下载这几样东西(下载链接),一个是他的范例代码,一个是他的签名生成工具。

2、如果你自己的APP想要微信第三方授权,你得去申请一个APPID,这个APPID呢,就是微信给咱们APP分配的一个代号。当然微信不是免费给你服务,为了获得这个第三方授权的功能,你得给微信交300块钱。申请到这个授权之后,你需要填写一个应用包名,和一个应用签名

应用包名

应用签名

使用签名生成工具,输入包名,查询到应用签名

 

3、然后打开DEMO

程序的入口WXEntryActivity是我们所最需要关注的 

1
2
3
4
5
// 微信发送请求到第三方应用时,会回调到该方法
@Override
public  void  onReq(BaseReq req) {
     // TODO
}

当点击授权登陆的界面的时候,会自动调用这个onResp方法,所以我们可以在这里面取得所需要token。注意andorid里叫token,ios里面叫code,而不是因为sdk版本的问题,这是需要注意的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
@Override
public  void  onResp(BaseResp resp) {
     int  result = 0;
     switch  (resp.errCode) {
         case  BaseResp.ErrCode.ERR_OK:
             result = R. string .errcode_success;
             /*获取token*/
             SendAuth.Resp sendResp = (SendAuth.Resp) resp;
             String code = sendResp.token;
             Log.d( "Tag" "code\t"  + code);
             break ;
         case  BaseResp.ErrCode.ERR_USER_CANCEL:
             result = R. string .errcode_cancel;
             break ;
         case  BaseResp.ErrCode.ERR_AUTH_DENIED:
             result = R. string .errcode_deny;
             break ;
         default :
             result = R. string .errcode_unknown;
             break ;
     }

 APP_ID 替换为你的应用从官方网站申请到的合法appId

1
2
3
4
public  class  Constants {
     // APP_ID 替换为你的应用从官方网站申请到的合法appId
     public  static  final String APP_ID =  "wx77777" ;
}

 

1
2
3
4
5
6
7
// IWXAPI 是第三方app和微信通信的openapi接口
private  IWXAPI api;
final SendAuth.Req req =  new  SendAuth.Req();
req.scope =  "snsapi_userinfo" ;
req.state =  "wechat_sdk_demo_test" ;
//发送授权登陆请求
api.sendReq(req);

这一步就是和微信要code。执行了这一段代码之后。微信会调用刚才WXEntityActivity类里面的onResp()方法。并且把code返回来了。见上面那一段代码。获取到code之后就可以通过code获取access_token了。 

请求以下链接获取access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

这步和微信通信获得access_token就是普通的访问链接。 用httpClient就行了,而不是接入指南里说的那个和微信通信的方法onReq().然后还是这样的方式通过access_token.就可以调用接口获得用户基本信息了。具体返回参数什么的接入指南里面说的很清楚。至此微信授权基本是成功了。

这里,我们要添加Custom debug keystore。上面的那个debug keystore不会和微信通信。

而我们添加的这个keystore 也要符合一些规范所以要改一改。

不过在开发的过程中要注意一下debug keystore。

步骤二 Android studio如何生成keystore文件

第一步 创建签名文件

第二步 填写签名参数

第三步 选择构建类型

第四步 查看生成第apk文件

步骤三 Android studio如何定位keystore文件

在运行微信分享Demo及新浪微博分享Demo时,需要修改使用Demo中的debug.keystore才能运行授权及和分享

在进行Android开发中,所用到的工具,就Eclispse和Android Studio比较多。其中,使用Eclipse里修改debug.keystore的方式新浪微博文档有介绍,在Eclipse里点击"Windows-->Preferences-->Android-->Build",在右边的"Custom debug keystore"选择Demo中的debug.keystore即可。

在Android Studio中的做法是"Project Structure"中“Modules”中的应用的模块。然后选择"Signing",点击"+"号,起名为“debug”,并在“Store File”里选择Demo中的debug.keystore,如下图

然后在选择“Build Types”在“debug”中的"Signing Config"选择上面配置的"debug",如下图

点击“OK”,重新编译就可以了。

通过上面配置完后,会自动在项目模块中的build.gradle里的android {}里生成

1
2
3
4
5
signingConfigs {
     debug {
         storeFile file( '.keystore里文件路径' )
     }
}

以及在buildTypes里生成

1
2
3
debug {
     signingConfig signingConfigs.debug
}

当然啦,可以不用界面配置,直接在build.gradle里写上面的配置也都OK的

步骤四 获取签名 填写到微信开发者平台

接下来将定位到jks文件的工程烧写到程序中,然后将签名工具的MD码填写到微信开发者平台,就能调用第三方授权登陆了。

 

效果图  

  

参考链接:

微信授权登陆接入第三方App(步骤总结)Android

Android Studio修改debug.keystore

Android Studio 签名打包过程图

需要参考以下网址:android 接入 微信

https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417751808&token=&lang=zh_CN

移动应用微信登录开发指南

https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317851&token=&lang=zh_CN

授权后接口调用(UnionID)

https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317853&token=&lang=zh_CN





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值