第三方授权登录(微博篇)

原创
2015/11/24 15:27
阅读数 2.1W

做过新浪微博第三方登录的朋友都清楚,他们的官方文档写的真心糟糕,添加新应用也很麻烦。我也是一边看文档,一边看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,有问题欢迎交流!!




展开阅读全文
打赏
2
3 收藏
分享
加载中
你好请问下 Web方式授权,为啥每次登入都要输入用户名和密码啊?
2016/06/13 15:00
回复
举报
你好 请问一下 那个和scope有关的高级界面 怎么弄才会出来
2016/04/06 16:51
回复
举报
更多评论
打赏
2 评论
3 收藏
2
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部