您的位置:首页 > 移动开发 > Android开发

Android仿人人客户端(v5.7.1)——人人授权访问界面

2013-03-27 12:19 501 查看
转载请标明出处:/article/7739541.html

声明:仿人人项目,所用所有图片资源都来源于官方人人android客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片。
以前在公司做Android应用(后面简称App)时的疑惑:
我只想实现用户可以用人人账号能登录我们的App,可以将自己在我们App中看到的,某些喜欢的内容分享给自己在人人上的朋友、同事和同学等。但是我又不想使用人人官方提供的SDK。理由:太大,有人可能要说,可以去掉没用到的类文件,我想说的是太费事了(我当时就这件事花了一天多时间);授权界面的Dialog觉得不美观,我自己得改。当时我就在想人人如果能提供一个小点的SDK只有我说的那两个功能就好了,欣赏大多数应用,里面用到人人提供的功能的就是我说的这两个。鉴于此,这次我不想使用人人提供的SDK(当然肯定会参考),所有功能自己编码实现,这对我来说是一个挑战,不过我喜欢这种有挑战的事。好了开始正题,这篇是在前面Android仿人人客户端(v5.7.1)——欢迎和导引界面的类图的基础上进行的,不明白可以查看下。

一、类图如下:



二、编码实现:

1、布局文件:

a. 主布局文件(auth.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<com.everyone.android.widget.TopNavbar
android:id="@+id/rl_top_navbar"
android:layout_width="fill_parent"
android:layout_height="50dip" />

<WebView
android:id="@+id/wv_auth"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

</LinearLayout>

b. 顶部工具栏(或者菜单栏)的布局文件(top_navbar.xml)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/top_navbar" >

<LinearLayout
android:id="@+id/ll_back"
android:layout_width="60dip"
android:layout_height="fill_parent"
android:background="@drawable/v5_0_1_flipper_head_title_wrapper_background"
android:gravity="center_vertical" >

<ImageView
android:id="@+id/iv_back"
android:layout_width="25dip"
android:layout_height="25dip"
android:layout_marginLeft="15dip"
android:src="@drawable/v5_0_1_flipper_head_back" />
</LinearLayout>

<ImageView
android:id="@+id/iv_line_separator"
android:layout_width="1dip"
android:layout_height="25dip"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/ll_back"
android:background="@drawable/v5_0_1_flipper_head_separator" />

<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="15dip"
android:layout_toRightOf="@+id/iv_line_separator"
android:text="人人授权访问"
android:textColor="#FFFFFF"
android:textSize="17dip"
android:textStyle="bold" />

</RelativeLayout>

2、应用授权界面的具体实现:

a. 初始组件:

@Override
protected void setupView() {
mTopNavbar = (TopNavbar) findViewById(R.id.rl_top_navbar);
mWebView = (WebView) findViewById(R.id.wv_auth);
mWebView.setVerticalScrollBarEnabled(false);
mWebView.setHorizontalScrollBarEnabled(false);
mWebView.getSettings().setJavaScriptEnabled(true);
}

b. 组拼请求参数

StringBuilder authorizeUrl = new StringBuilder(Constant.AUTHORIZE_URL);
authorizeUrl.append("?");
authorizeUrl.append("client_id=").append(Constant.API_KEY);
authorizeUrl.append("&redirect_uri=").append(Constant.DEFAULT_REDIRECT_URI);
authorizeUrl.append("&response_type=").append("token");
authorizeUrl.append("&display=").append("touch");
String scope = TextUtils.join(" ", Constant.HAVE_PERMISSIONS);
authorizeUrl.append("&scope=").append(scope);
Log.i(TAG, "authorizeUrl = " + authorizeUrl.toString());

c. 使用WebView组件加载授权界面

mWebView.loadUrl(authorizeUrl.toString());

// 以POST方式请求
// mWebView.postUrl(Constant.AUTHORIZE_URL, EncodingUtils.getBytes(sb.toString(), "BASE64"));
mWebView.setWebViewClient(new WebViewClient() {

public boolean shouldOverrideUrlLoading(WebView webView, String url) {
Log.i(TAG, "shouldOverrideUrlLoading() Redirect URL = " + url);

if (url.startsWith(Constant.DEFAULT_REDIRECT_URI + "#error=login_denied")) {
AuthActivity.this.onBackPressed();
} else if(url.startsWith("http://graph.renren.com/oauth/login_success.html#access_token")) {
String accessToken = url.substring(url.indexOf("="), url.indexOf("&"));
Log.i(TAG, "accessToken = " + accessToken);

AuthActivity.this.onBackPressed();
return false;
}

webView.loadUrl(url);
return true;
}

public void onReceivedSslError(WebView view, SslErrorHandler handler, android.net.http.SslError errorCode) {
// 在默认情况下,通过loadUrl(String url)方法,可以顺利load。
// 但是,当load有ssl层的https页面时,如果这个网站的安全证书在Android无法得到认证,WebView就会变成一个空白页,
// 而并不会像PC浏览器中那样跳出一个风险提示框。因此,我们必须针对这种情况进行处理。(这个证书限于2.1版本以上的Android 系统才可以)

// 默认的处理方式,WebView变成空白页
// handler.cancel();

// 接受证书
handler.proceed();
}

@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
AuthActivity.this.onBackPressed();
}

public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.i(TAG, "Webview loading URL: " + url);
super.onPageStarted(view, url, favicon);
}

public void onPageFinished(WebView view, String url) {
Log.i(TAG, "onPageFinished() url = " + url);
super.onPageFinished(view, url);
}
});

d. Back键事件处理

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (mWebView != null) {
mWebView.stopLoading();
}
}
return super.onKeyDown(keyCode, event);
}

应用授权界面,完整代码:

package com.everyone.android.ui;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.everyone.android.AppBaseActivity;
import com.everyone.android.R;
import com.everyone.android.utils.Constant;
import com.everyone.android.widget.TopNavbar;

/**
* 功能描述:应用授权界面
* @author android_ls
*/
public class AuthActivity extends AppBaseActivity {

/**
* 打印Log的标签
*/
private static final String TAG = "AuthActivity";

private WebView mWebView;

private TopNavbar mTopNavbar;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// 顶部返回按钮事件处理
mTopNavbar.llBack.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
onBackPressed();
}
});

}

@Override
protected void setupView() {
mTopNavbar = (TopNavbar) findViewById(R.id.rl_top_navbar);
mWebView = (WebView) findViewById(R.id.wv_auth);
mWebView.setVerticalScrollBarEnabled(false);
mWebView.setHorizontalScrollBarEnabled(false);
mWebView.getSettings().setJavaScriptEnabled(true);
}

@Override
protected int getLayoutId() {
return R.layout.auth;
}

@Override
protected void initializedData() {
// 组拼请求参数
StringBuilder authorizeUrl = new StringBuilder(Constant.AUTHORIZE_URL);
authorizeUrl.append("?");
authorizeUrl.append("client_id=").append(Constant.API_KEY);
authorizeUrl.append("&redirect_uri=").append(Constant.DEFAULT_REDIRECT_URI);
authorizeUrl.append("&response_type=").append("token");
authorizeUrl.append("&display=").append("touch");
String scope = TextUtils.join(" ", Constant.HAVE_PERMISSIONS);
authorizeUrl.append("&scope=").append(scope);
Log.i(TAG, "authorizeUrl = " + authorizeUrl.toString());

mWebView.loadUrl(authorizeUrl.toString());

// 以POST方式请求
// mWebView.postUrl(Constant.AUTHORIZE_URL, EncodingUtils.getBytes(sb.toString(), "BASE64"));
mWebView.setWebViewClient(new WebViewClient() {

public boolean shouldOverrideUrlLoading(WebView webView, String url) {
Log.i(TAG, "shouldOverrideUrlLoading() Redirect URL = " + url);

if (url.startsWith(Constant.DEFAULT_REDIRECT_URI + "#error=login_denied")) {
AuthActivity.this.onBackPressed();
} else if(url.startsWith("http://graph.renren.com/oauth/login_success.html#access_token")) {
String accessToken = url.substring(url.indexOf("="), url.indexOf("&"));
Log.i(TAG, "accessToken = " + accessToken);

AuthActivity.this.onBackPressed();
return false;
}

webView.loadUrl(url);
return true;
}

public void onReceivedSslError(WebView view, SslErrorHandler handler, android.net.http.SslError errorCode) {
// 在默认情况下,通过loadUrl(String url)方法,可以顺利load。
// 但是,当load有ssl层的https页面时,如果这个网站的安全证书在Android无法得到认证,WebView就会变成一个空白页,
// 而并不会像PC浏览器中那样跳出一个风险提示框。因此,我们必须针对这种情况进行处理。(这个证书限于2.1版本以上的Android 系统才可以)

// 默认的处理方式,WebView变成空白页
// handler.cancel();

// 接受证书
handler.proceed();
}

@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
AuthActivity.this.onBackPressed();
}

public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.i(TAG, "Webview loading URL: " + url);
super.onPageStarted(view, url, favicon);
}

public void onPageFinished(WebView view, String url) {
Log.i(TAG, "onPageFinished() url = " + url);
super.onPageFinished(view, url);
}
});
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (mWebView != null) {
mWebView.stopLoading();
}
}
return super.onKeyDown(keyCode, event);
}

}

TopNavbar类:

package com.everyone.android.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.everyone.android.R;

/**
* 功能描述:自定义顶部工具栏
* @author android_ls
* 创建日期:2013-03-26
*/
public class TopNavbar extends FrameLayout {

public TextView tvTitle;

public LinearLayout llBack;

public TopNavbar(Context context) {
super(context);
setupViews();
}

public TopNavbar(Context context, AttributeSet attrs) {
super(context, attrs);
setupViews();
}

private void setupViews() {
final LayoutInflater mLayoutInflater = LayoutInflater.from(getContext());
RelativeLayout rlTopNavbar = (RelativeLayout) mLayoutInflater.inflate(R.layout.top_navbar, null);
addView(rlTopNavbar);

llBack = (LinearLayout) rlTopNavbar.findViewById(R.id.ll_back);
tvTitle = (TextView) rlTopNavbar.findViewById(R.id.tv_title);
}

}

常量类:

package com.everyone.android.utils;

/**
* 功能描述:常量类
* @author android_ls
*/
public class Constant {

/**
* 人人登录和授权的地址
*/
public static final String AUTHORIZE_URL = "https://graph.renren.com/oauth/authorize";

/**
* 默认重定向URL
*/
public static final String DEFAULT_REDIRECT_URI = "http://graph.renren.com/oauth/login_success.html";

/**
* 第三方应用所拥有的权限
*/
public static final String[] HAVE_PERMISSIONS = { "publish_feed", "create_album", "photo_upload", "read_user_album", "status_update",
"read_user_blog", "read_user_checkin", "read_user_feed", "read_user_guestbook", "read_user_invitation", "read_user_like_history",
"read_user_message", "read_user_notification", "read_user_photo", "read_user_status", "read_user_comment", "read_user_share",
"read_user_request", "publish_blog", "publish_checkin", "publish_feed", "publish_share", "write_guestbook", "send_invitation",
"send_request", "send_message", "send_notification", "photo_upload", "create_album", "publish_comment", "operate_like", "admin_page" };

/**
* API_KEY
*/
public static final String API_KEY = "661ea1ba2d6b49859be197d77fe361f1";

/**
* Secret Key
*/
public static final String SECRET_KEY = "a088d31cd5d341819bfc75ac0208b5e1";

/**
* 应用ID
*/
public static final String APP_ID = "195789";

}


三、运行效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐