QQ授权登入(Android SDK3.1)
SDK下载 (最新3.1):http://connect.qq.com/intro/login
1.自己创建应用
首先我们打开腾讯开发平台这个网页,点击—->移动应用—->创建应用,成功创建应用后,可以产生我们需要的App ID和App Key,如下图所示:
2.运行官方Demo(官方Demo比较全,可以根据自己需求使用,我们在这里只分析登入的代码)
下面是主要的登录代码,在Demo的MainActivity里面
/** * * 通过调用Tencent类的login函数发起登录/校验登录态。 * * 该API具有两个作用: * (1)如果开发者没有调用mTencent实例的setOpenId,setAccessToken API,则该API执行正常的登录操作; * (2)如果开发者先调用mTencent实例的setOpenId、setAccessToken * API,则该API执行校验登录态的操作。如果登录态有效,则返回成功给应用, * 如果登录态失效,则会自动进入登录流程,将最新的登录态数据返回给应用 * * @author super bear * */
public class MainActivity extends Activity {private static final String TAG = MainActivity.class.getName();public static String mAppid;private Button mNewLoginButton;private Button mServerSideLoginBtn;private TextView mUserInfo;private ImageView mUserLogo;private UserInfo mInfo;private EditText mEtAppid = null;public static Tencent mTencent;private static Intent mPrizeIntent = null;private static boolean isServerSideLogin = false;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.d(TAG, "-->onCreate");// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//// 固定竖屏setContentView(R.layout.activity_main_new);initViews();//setBarTitle("demo菜单");if (TextUtils.isEmpty(mAppid)) {mAppid = "222222";mEtAppid = new EditText(this);mEtAppid.setText(mAppid);try {new AlertDialog.Builder(this).setTitle("请输入APP_ID").setCancelable(false).setIcon(android.R.drawable.ic_dialog_info).setView(mEtAppid).setPositiveButton("Commit", mAppidCommitListener).setNegativeButton("Use Default", mAppidCommitListener).show();} catch (Exception e) {}} else {if (mTencent == null) {mTencent = Tencent.createInstance(mAppid, this);}}// 获取有奖分享的intent信息if (null != getIntent()) {mPrizeIntent = getIntent();}}/*** 有奖分享处理,未接入有奖分享可以不考虑*/private void handlePrizeShare() {// -----------------------------------// 下面的注释请勿删除,编译lite版的时候需要删除, 注意//[不要有空格。//[liteexludestartmeta]if (null == mPrizeIntent || null == mTencent) {return;}// 有奖分享处理boolean hasPrize = mTencent.checkPrizeByIntent(this, mPrizeIntent);if (hasPrize) {Util.showConfirmCancelDialog(this, "有奖品领取", "请使用QQ登录后,领取奖品!", prizeShareConfirmListener);}//[liteexludeendmeta]}// -----------------------------------// 下面的注释请勿删除,编译lite版的时候需要删除, 注意//[不要有空格。//[liteexludestart_flag_one]private DialogInterface.OnClickListener prizeShareConfirmListener = new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {switch (which) {case DialogInterface.BUTTON_POSITIVE:boolean isLogin = mTencent.isSessionValid();if (isLogin) {// 本地已经有保存openid和accesstoken的情况下,先调用mTencent.setAccesstoken().// 也可在奖品列表页,主动调用此接口获取未领取的奖品if (null != mPrizeIntent) {mTencent.queryUnexchangePrize(MainActivity.this, mPrizeIntent.getExtras(),prizeQueryUnexchangeListener);}} else {// 未登陆提示用户使用QQ号登陆onClickLogin();}break;default:break;}}};private IUiListener prizeQueryUnexchangeListener = new IUiListener() {@Overridepublic void onError(UiError e) {Util.toastMessage(MainActivity.this, "onError: " + e.errorDetail);Util.dismissDialog();}@Overridepublic void onCancel() {Util.toastMessage(MainActivity.this, "onCancel: ");Util.dismissDialog();}@Overridepublic void onComplete(Object response) {Util.showConfirmCancelDialog(MainActivity.this, "兑换奖品", response.toString(),new PrizeClickExchangeListener(response.toString()));// 兑换奖品后,mPrizeIntent 置为空mPrizeIntent = null;}};private IUiListener prizeExchangeListener = new IUiListener() {@Overridepublic void onError(UiError e) {Util.toastMessage(MainActivity.this, "onError: " + e.errorDetail);Util.dismissDialog();}@Overridepublic void onCancel() {Util.toastMessage(MainActivity.this, "onCancel: ");Util.dismissDialog();}@Overridepublic void onComplete(Object response) {Util.showResultDialog(MainActivity.this, response.toString(), "兑换信息");}};private class PrizeClickExchangeListener implements DialogInterface.OnClickListener {String response = "";PrizeClickExchangeListener(String strResponse) {response = strResponse;}@Overridepublic void onClick(DialogInterface dialog, int which) {switch (which) {case DialogInterface.BUTTON_POSITIVE:if (null != mTencent) {Bundle params = new Bundle();ArrayList<String> shareIdList = handlePrizeResponse(response);if (null != shareIdList) {ArrayList<String> list = new ArrayList<String>();// 后台测试环境目前只支持一个shareid的兑换,正式环境会支持多个shareid兑换。list.add(shareIdList.get(0));params.putStringArrayList("shareid_list", list);mTencent.exchangePrize(MainActivity.this, params, prizeExchangeListener);}}break;default:break;}}};private ArrayList<String> handlePrizeResponse(String response) {ArrayList<String> shareIdList = new ArrayList<String>();if (TextUtils.isEmpty(response)) {return null;}try {JSONObject obj = new JSONObject(response);int code = obj.getInt("ret");int subCode = obj.getInt("subCode");if (code == 0 && subCode == 0) {JSONObject data = obj.getJSONObject("data");JSONArray prizeList = data.getJSONArray("prizeList");int size = prizeList.length();JSONObject prize = null;for (int i = 0; i < size; i++) {prize = prizeList.getJSONObject(i);if (null != prize) {shareIdList.add(prize.getString("shareId"));}}} else {return null;}} catch (Exception e) {return null;}return shareIdList;}//[liteexludeend_flag_one]@Overrideprotected void onStart() {Log.d(TAG, "-->onStart");super.onStart();}@Overrideprotected void onResume() {Log.d(TAG, "-->onResume");// 有奖分享处理handlePrizeShare();super.onResume();}@Overrideprotected void onPause() {Log.d(TAG, "-->onPause");super.onPause();}@Overrideprotected void onStop() {Log.d(TAG, "-->onStop");super.onStop();}@Overrideprotected void onDestroy() {Log.d(TAG, "-->onDestroy");super.onDestroy();}private void initViews() {mNewLoginButton = (Button) findViewById(R.id.new_login_btn);mServerSideLoginBtn = (Button) findViewById(R.id.server_side_login_btn);LinearLayout linearLayout = (LinearLayout) findViewById(R.id.main_container);OnClickListener listener = new NewClickListener();for (int i = 0; i < linearLayout.getChildCount(); i++) {View view = linearLayout.getChildAt(i);if (view instanceof Button) {view.setOnClickListener(listener);}}mUserInfo = (TextView) findViewById(R.id.user_nickname);mUserLogo = (ImageView) findViewById(R.id.user_logo);updateLoginButton();}private void updateLoginButton() {if (mTencent != null && mTencent.isSessionValid()) {if (isServerSideLogin) {mNewLoginButton.setTextColor(Color.BLUE);mNewLoginButton.setText("登录");mServerSideLoginBtn.setTextColor(Color.RED);mServerSideLoginBtn.setText("退出Server-Side账号");} else {mNewLoginButton.setTextColor(Color.RED);mNewLoginButton.setText("退出帐号");mServerSideLoginBtn.setTextColor(Color.BLUE);mServerSideLoginBtn.setText("Server-Side登陆");}} else {mNewLoginButton.setTextColor(Color.BLUE);mNewLoginButton.setText("登录");mServerSideLoginBtn.setTextColor(Color.BLUE);mServerSideLoginBtn.setText("Server-Side登陆");}}private void updateUserInfo() {if (mTencent != null && mTencent.isSessionValid()) {IUiListener listener = new IUiListener() {@Overridepublic void onError(UiError e) {}@Overridepublic void onComplete(final Object response) {Message msg = new Message();msg.obj = response;msg.what = 0;mHandler.sendMessage(msg);new Thread(){@Overridepublic void run() {JSONObject json = (JSONObject)response;if(json.has("figureurl")){Bitmap bitmap = null;try {bitmap = Util.getbitmap(json.getString("figureurl_qq_2"));} catch (JSONException e) {}Message msg = new Message();msg.obj = bitmap;msg.what = 1;mHandler.sendMessage(msg);}}}.start();}@Overridepublic void onCancel() {}};mInfo = new UserInfo(this, mTencent.getQQToken());mInfo.getUserInfo(listener);} else {mUserInfo.setText("");mUserInfo.setVisibility(android.view.View.GONE);mUserLogo.setVisibility(android.view.View.GONE);}}Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg.what == 0) {JSONObject response = (JSONObject) msg.obj;if (response.has("nickname")) {try {mUserInfo.setVisibility(android.view.View.VISIBLE);mUserInfo.setText(response.getString("nickname"));} catch (JSONException e) {e.printStackTrace();}}}else if(msg.what == 1){Bitmap bitmap = (Bitmap)msg.obj;mUserLogo.setImageBitmap(bitmap);mUserLogo.setVisibility(android.view.View.VISIBLE);}}};private void onClickLogin() {if (!mTencent.isSessionValid()) {mTencent.login(this, "all", loginListener);isServerSideLogin = false;Log.d("SDKQQAgentPref", "FirstLaunch_SDK:" + SystemClock.elapsedRealtime());} else {if (isServerSideLogin) { // Server-Side 模式的登陆, 先退出,再进行SSO登陆mTencent.logout(this);mTencent.login(this, "all", loginListener);isServerSideLogin = false;Log.d("SDKQQAgentPref", "FirstLaunch_SDK:" + SystemClock.elapsedRealtime());return;}mTencent.logout(this);updateUserInfo();updateLoginButton();}}private void onClickServerSideLogin() {if (!mTencent.isSessionValid()) {mTencent.loginServerSide(this, "all", loginListener);isServerSideLogin = true;Log.d("SDKQQAgentPref", "FirstLaunch_SDK:" + SystemClock.elapsedRealtime());} else {if (!isServerSideLogin) { // SSO模式的登陆,先退出,再进行Server-Side模式登陆mTencent.logout(this);mTencent.loginServerSide(this, "all", loginListener);isServerSideLogin = true;Log.d("SDKQQAgentPref", "FirstLaunch_SDK:" + SystemClock.elapsedRealtime());return;}mTencent.logout(this);isServerSideLogin = false;updateUserInfo();updateLoginButton();}}public static String getAppid() {if (TextUtils.isEmpty(mAppid)) {mAppid = "222222";}return mAppid;}public static boolean ready(Context context) {if (mTencent == null) {return false;}boolean ready = mTencent.isSessionValid()&& mTencent.getQQToken().getOpenId() != null;if (!ready) {Toast.makeText(context, "login and get openId first, please!",Toast.LENGTH_SHORT).show();}return ready;}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {Log.d(TAG, "-->onActivityResult " + requestCode + " resultCode=" + resultCode);if (requestCode == Constants.REQUEST_LOGIN ||requestCode == Constants.REQUEST_APPBAR) {Tencent.onActivityResultData(requestCode,resultCode,data,loginListener);}super.onActivityResult(requestCode, resultCode, data);}public static void initOpenidAndToken(JSONObject jsonObject) {try {String token = jsonObject.getString(Constants.PARAM_ACCESS_TOKEN);String expires = jsonObject.getString(Constants.PARAM_EXPIRES_IN);String openId = jsonObject.getString(Constants.PARAM_OPEN_ID);System.out.println("token"+token+"-------------"+openId);if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expires)&& !TextUtils.isEmpty(openId)) {mTencent.setAccessToken(token, expires);mTencent.setOpenId(openId);}} catch(Exception e) {}}IUiListener loginListener = new BaseUiListener() {@Overrideprotected void doComplete(JSONObject values) {Log.d("SDKQQAgentPref", "AuthorSwitch_SDK:" + SystemClock.elapsedRealtime());initOpenidAndToken(values);updateUserInfo();updateLoginButton();}};private class BaseUiListener implements IUiListener {@Overridepublic void onComplete(Object response) {if (null == response) {Util.showResultDialog(MainActivity.this, "返回为空", "登录失败");return;}JSONObject jsonResponse = (JSONObject) response;if (null != jsonResponse && jsonResponse.length() == 0) {Util.showResultDialog(MainActivity.this, "返回为空", "登录失败");return;}Util.showResultDialog(MainActivity.this, response.toString(), "登录成功");// 有奖分享处理handlePrizeShare();doComplete((JSONObject)response);}protected void doComplete(JSONObject values) {}@Overridepublic void onError(UiError e) {Util.toastMessage(MainActivity.this, "onError: " + e.errorDetail);Util.dismissDialog();}@Overridepublic void onCancel() {Util.toastMessage(MainActivity.this, "onCancel: ");Util.dismissDialog();if (isServerSideLogin) {isServerSideLogin = false;}}}private DialogInterface.OnClickListener mAppidCommitListener = new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {mAppid = AppConstants.APP_ID;switch (which) {case DialogInterface.BUTTON_POSITIVE:// 用输入的appidString editTextContent = mEtAppid.getText().toString().trim();if (!TextUtils.isEmpty(editTextContent)) {mAppid = editTextContent;}break;case DialogInterface.BUTTON_NEGATIVE:// 默认appidbreak;}mTencent = Tencent.createInstance(mAppid, MainActivity.this);// 有奖分享处理handlePrizeShare();}};private void onClickIsSupportSSOLogin() {if (mTencent.isSupportSSOLogin(MainActivity.this)) {Toast.makeText(MainActivity.this, "支持SSO登陆", Toast.LENGTH_SHORT).show();} else {Toast.makeText(MainActivity.this, "不支持SSO登陆", Toast.LENGTH_SHORT).show();}}class NewClickListener implements OnClickListener {@Overridepublic void onClick(View v) {Context context = v.getContext();Animation shake = AnimationUtils.loadAnimation(context,R.anim.shake);Class<?> cls = null;boolean isAppbar = false;switch (v.getId()) {case R.id.new_login_btn:onClickLogin();v.startAnimation(shake);return;case R.id.server_side_login_btn:onClickServerSideLogin();v.startAnimation(shake);return;case R.id.main_sso_btn:onClickIsSupportSSOLogin();return;case R.id.main_getInfo_btn:cls = AccountInfoActivity.class;break;case R.id.main_qqShare_btn:cls = QQShareActivity.class;break;case R.id.main_qzoneShare_btn:cls = QZoneShareActivity.class;break;case R.id.main_social_api_btn:cls = SocialApiActivity.class;break;//-----------------------------------// 下面的注释请勿删除,编译lite版的时候需要删除, 注意//[不要有空格。//[liteexludestart]case R.id.game_add_friend:cls = GameLogicActivity.class;break;case R.id.main_qzonePic_btn:cls = QzonePicturesActivity.class;break;case R.id.main_tqqInfo_btn:cls = TQQInfoActivity.class;break;case R.id.main_wap_btn:cls = WPAActivity.class;break;case R.id.main_others_btn:cls = OtherApiActivity.class;break;case R.id.main_avatar_btn:cls = AvatarActivity.class;break;case R.id.main_appbar_btn:cls = SocialAppbarActivity.class;isAppbar = true;break;case R.id.main_qqgroup_btn:cls = QQGroupActivity.class;break;//[liteexludeend]}v.startAnimation(shake);if (cls != null) {Intent intent = new Intent(context, cls);if (isAppbar) { //APP内应用吧登录需接收登录结果startActivityForResult(intent, Constants.REQUEST_APPBAR);} else {context.startActivity(intent);}}}}
}
在主程序里面实现登录和获取用户信息,主要起作用的语句:
mTencent.login(MainActivity.this, scope, loginListener); //登录
userInfo = new UserInfo(MainActivity.this, mTencent.getQQToken()); //获取用户信息
userInfo.getUserInfo(userInfoListener);
3.配置AndroidManifest
在应用的AndroidManifest.xml增加配置的<application>节点下增加以下配置(注:不配置将会导致无法调用API);
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><application><activity
android:name="com.tencent.tauth.AuthActivity"android:noHistory="true"android:launchMode="singleTask" ><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><data android:scheme="tencent你的AppId" /></intent-filter></activity>
<application>其中,如果你已经添加了"android.permission.INTERNET"和"android.permission.ACCESS_NETWORK_STATE"权限,则无需重复添加。
而"你的AppId"则要替换成具体应用的AppId,例如你的AppId是"222222",则<data>标签应该是这样的:
<data android:scheme="tencent222222" />
4.初始化实例
@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// Tencent类是SDK的主要实现类,开发者可通过Tencent类访问腾讯开放的OpenAPI。// 其中APP_ID是分配给第三方应用的appid,类型为String。mTencent = Tencent.createInstance(APP_ID, this.getApplicationContext());
// 1.4版本:此处需新增参数,传入应用程序的全局context,可通过activity的getApplicationContext方法获取
// 初始化视图
initViews();}
5.登录按钮被点击的代码
private void onClickLogin() {if (!mTencent.isSessionValid()) {mTencent.login(this, "all", loginListener);isServerSideLogin = false;Log.d("SDKQQAgentPref", "FirstLaunch_SDK:" + SystemClock.elapsedRealtime());} else {if (isServerSideLogin) { // Server-Side 模式的登陆, 先退出,再进行SSO登陆mTencent.logout(this);mTencent.login(this, "all", loginListener);isServerSideLogin = false;Log.d("SDKQQAgentPref", "FirstLaunch_SDK:" + SystemClock.elapsedRealtime());return;}mTencent.logout(this);updateUserInfo();updateLoginButton();}}
6.实现回调
//这个是登录时传递进去的接口
IUiListener loginListener = new BaseUiListener() {@Overrideprotected void doComplete(JSONObject values) {Log.d("SDKQQAgentPref", "AuthorSwitch_SDK:" + SystemClock.elapsedRealtime());//去获取Token与OpenIdinitOpenidAndToken(values);}};--------------------华丽的分割线--------------------------------private class BaseUiListener implements IUiListener {@Overridepublic void onComplete(Object response) {if (null == response) {Util.showResultDialog(MainActivity.this, "返回为空", "登录失败");return;}JSONObject jsonResponse = (JSONObject) response;if (null != jsonResponse && jsonResponse.length() == 0) {Util.showResultDialog(MainActivity.this, "返回为空", "登录失败");return;}Util.showResultDialog(MainActivity.this, response.toString(), "登录成功");// 有奖分享处理handlePrizeShare();doComplete((JSONObject)response);}protected void doComplete(JSONObject values) {}@Overridepublic void onError(UiError e) {Util.toastMessage(MainActivity.this, "onError: " + e.errorDetail);Util.dismissDialog();}@Overridepublic void onCancel() {Util.toastMessage(MainActivity.this, "onCancel: ");Util.dismissDialog();if (isServerSideLogin) {isServerSideLogin = false;}}}--------------------华丽的分割线--------------------------------
//去拿到ACCESS_TOKEN与PARAM_OPEN_ID与EXPIRES_IN(有效时间)public static void initOpenidAndToken(JSONObject jsonObject) {try {String token = jsonObject.getString(Constants.PARAM_ACCESS_TOKEN);String expires = jsonObject.getString(Constants.PARAM_EXPIRES_IN);String openId = jsonObject.getString(Constants.PARAM_OPEN_ID);System.out.println("token"+token+"-------------"+openId);if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expires)&& !TextUtils.isEmpty(openId)) {mTencent.setAccessToken(token, expires);mTencent.setOpenId(openId);}} catch(Exception e) {}}
7.使用access_token和openid
应用在每次登录之后,都会获取到openid、access_token和expires_in,在调用SDK提供的接口时,后台会根据这三个参数来验证请求的合法性。
(1)如果应用已经走过登录流程,调用应用分享、邀请等接口,是不需要再将这三个参数传入到请求参数中去的,这是因为在登录成功后,SDK会自动将这几个参数保存在SDK的上下文中,在发送请求时,会自动为请求加上这些参数。
(2)如果应用不希望每次都走登录流程来使用SDK的功能,可以通过以下步骤来实现:
Step1:在首次登录成功后,将返回的openid、access_token、expires_in三个参数保存在本地(比如保存在sharedPreferrence)。其中expires_in参数在存储前需进行如下计算:
1.System.currentTimeMillis() + Long.parseLong(expires_in) * 1000;
这样得出的就是token的失效日期。
Step2:在用户下次进入应用,发起应用分享等SDK调用之前,首先创建Tencent实例,然后取出之前保存的openid、access_token、expires_in(前面计算出来的值)的值。Step3:调用Tencent类的setOpenId和setAccessToken方法。其中setOpenId的参数传入上一步取出的openid,setAccessToken的第一个参数传入上一步取出的access_token,第二个参数传入(上一步保存的token失效日期-当前系统时间)/1000。这里计算出的结果是当前保存的token的有效时间,如果结果小于或等于0,表示token已经过期,应该提示用户重新走登录流程。
免登录流程调用SDK接口的示例代码如下(省去了获取存储的变量的过程):
String openid = "1234567896ASDFGHJKLLIUYT";String access_token = "2C0884DC4B930010D852D8D504FC9F4D";String expires_in = "7776000"; // 实际值需要通过上面介绍的方法来计算mTencent = Tencent.createInstance(APP_ID);mTencent.setOpenId(openid);mTencent.setAccessToken(access_token, expires_in);
8.混淆
-keep class com.tencent.open.TDialog$*-keep class com.tencent.open.TDialog$* {*;}-keep class com.tencent.open.PKDialog-keep class com.tencent.open.PKDialog {*;}-keep class com.tencent.open.PKDialog$*-keep class com.tencent.open.PKDialog$* {*;}
微信授权登录可以参考下面博客
http://blog.csdn.net/qq247890212/article/details/40822481
QQ授权登入(Android SDK3.1)相关推荐
- [Android]-SDK QQ微信登入
在Unity中接入大量SDK,对一个零Android开发基础的人来说还是比较蛋疼的.在网上搜了一大堆资料,总算折腾出一个能用的QQ&微信登入SDK. 在QQ互联和微信开放平台注册,并申请相关权 ...
- 微信wechat.class.php,laravel使用组件实现微信网页授权登入
laravel框架中的实现简单实现微信网页授权登入 首先引入基于laravel的easywechat的组件,laravel版本5.8 $ cd laravel $ composer require & ...
- 微信网页授权登入--laravel组件 laravel-wechat调用
组件地址:https://github.com/overtrue/laravel-wechat laravel框架中的实现简单实现微信网页授权登入,首先引入基于laravel的easywechat的组 ...
- php网站 qq登陆,PHP QQ一键登入网站实现过程
qq一键登入功能对于大多数小中型网站来说是十分必要的,因为他给你的用户带来了极大的方便,但是想要集成网站的qq一键登入功能,你必须要一些编程基础,使网站和qq登入的应用之间进行一些必要的交互,下面我简 ...
- Springboot集成QQ平台互联授权登入应用
1.QQ互联文档地址: QQ互联平台文档 注册地址: 个人开发 2.OAuth 2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据. OAuth 2.0文档 配置文件模板:() app_ ...
- 用QQ邮箱登入foxmail出现问题
如果你的qq邮箱无法登入foxmail时,而且总是显示你的密码或邮箱有误并且你确定没错时.那么很有可能是你的qq邮箱没有开启pop3/smtp服务: 以下是开通流程: 打开你的qq邮箱,进入首页,然后 ...
- qq一键登入帝国cms插件|适用7.5 7.2版本|UTF-8 GBK双版本
简介: 帝国CMS啥插件都有,这款QQ登入插件,快快拿去用吧,非常方便,傻瓜式设置. 网盘下载地址: http://kekewangLuo.cc/81N8Y2qFUcd0 安装插件: 1.将" ...
- 如何实现QQ的登入界面
历经三天终于实现QQ账号的模样 哈哈 还被室友说了 目标状态
- QQ同步登入出现 回调地址非法,请使用已注册的回调地址(21006)!错误解决办法
错误信息:回调地址非法,请使用已注册的回调地址(21006)! 解决办法是在: 只需要在connect.qq.com后台将回调地址参数修改为http://www.xxx.com(注你的域名)就可以解决 ...
最新文章
- python入门编程题库-Python经典基础编程练习题(六)——每日10题
- FPN(Feature Pyramid Network)多尺度目标检测方案
- MyBatis 架构分层与模块划分-接口层
- 队列 开源 php,消息队列 - 基于think-queue消息队列 – 基于ThinkPHP和Bootstrap的极速后台开发框架...
- 使用JavaScript弹出Confirm对话框
- ajax post请求怎么传参_如何在$ ajax POST中传递参数?
- 【文本处理】格式crs_stat输出
- C#实现HTTP下载文件的方法
- 常用的ASCII码值
- Qt VS Tools插件官方下载及安装
- SURF(Speeded Up Robust Features)算法原理
- Order Siblings by 排序
- iphone11拍照没有咔嚓声
- HLS 开发学习(五) 稀疏矩阵向量乘法
- 程序员推荐的5种编程语言!
- 记一次查询超时的解决方案The timeout period elapsed......
- js:Vue.js自定义指令实现scroll下滑滚动翻页
- OTA 升级中的跟文件系统切换
- vue项目添加百度统计
- 大数据实时案例--实时日志监控告警系统
热门文章
- javacv实现实时视频截图和录像服务easyCV,支持png,jpg截图以及gif,apng动态图片录制
- 在中国,营销自动化会和销售自动化一样成为一个笑话
- oracle dg 数据不一致,DG常用运维命令及常见问题解决
- 智能的PHP开发工具PhpStorm v2023.1全新发布——集成3v4l.org
- 运行dcnv3代码的警告及解决方法
- PyCharm使用技巧:Structure(列出代码结构)
- Wio Terminal 天气小助手(Funpack 项目)
- 对用友/金蝶/博科/新中大/金算盘/神州数码/思爱普/甲骨文的分析
- 7天物联网智能家居实战-DAY1
- python入门教程 - 滑块实战[附源码]