Facebook API 简介
2011-01-14 16:55 王克伟 阅读(13821) 评论(2) 编辑 收藏 举报原文:http://www.ibm.com/developerworks/cn/xml/x-androidfacebookapi/index.html
在介绍 Facebook SDK for Android 之前,有必要了解一下 Facebook Platform 及其 API。据 Facebook 声称,Facebook Platform 允许任何人 “在 Facebook 和 Web 上构建社交应用程序”。为了允许您构建此类应用程序,Facebook 提供广泛的一组核心且高级的 API 和 SDK(参见 参考资料)。
核心 Facebook Platform API 是 Graph API,它允许您从 Facebook 读写数据。Facebook 也具有 Old Rest API。新的 Graph API 将 API 范型从面向方法的从 Facebook 读写数据的方式更改为一种新的方式,即使用对象(比如说用户简介、好友、帖子、照片,诸如此类)及其相互之间的关系或连接。该方法简化了 Facebook API,使之处理对象时更加一致。注意,尽管 Graph API 是首选的 Facebook API,但是 Old REST API 仍然是活跃且受支持的。Graph 和 REST API 都适用于移动应用程序(包括原生和移动 web 应用程序),它们通过使用 WebViews 在原生应用程序中包含移动 web 内容。
Graph API 对象被分配一个惟一的 ID,很容易使用一个 URL 访问它,此 URL 可被进一步限定,以寻址一个特定的对象/连接。对象 URL 的一般结构类似如下: https://graph.facebook.com/OBJECT_ID/CONNECTION_TYPE
,其中 OBJECT_ID
是对象的惟一 ID,CONNECTION_TYPE
是对象支持的一种连接类型。例如,一个页面支持以下连接:feed/wall、photos、notes、posts、members,等等。
利用 Graph API,您可以检索对象,删除对象和发布对象。您可以搜索、更新对象、过滤结果,甚至动态地发现对象的连接/关系。
默认情况下,应用程序对用户的公共数据具有访问权限。要访问私有数据,应用程序必须首先请求用户的权限(被称之为扩展权限)。Facebook 定义了大量权限,您可以在 Extended Permissions 页面了解它们(参见 参考资料)。
既然您较好地了解了 Facebook Platform API,下面就来看一下 Facebook SDK for Android。
Facebook SDK for Android 是 Facebook Graph 和 Old REST API 的一个 Java 编程语言包装器。此 SDK 是开源的,宿主在 github 的 facebook / facebook-android-sdk 仓库中(参见 参考资料)。注意,由于开源 SDK 的演变特性,它有望发生进一步的更改。SDK 发布于 Apache License, Version 2.0 之下。
Facebook SDK for Android 隐藏了前一节(Facebook Platform API 概述)中介绍的很多细节。这是通过提供 表 1 中描述的 6 个 Java 类来实现的。
类
说明
AsyncFacebookRunner
一个实现异步 Facebook API 调用的帮助器类
DialogError
一个封装对话框错误的类
Facebook
用于与 Facebook Platform API 交互的主 Facebook 类
FacebookError
一个封装 Facebook 错误的类
FbDialog
一个为 Facebook 对话框实现 WebView 的类
Util
一个带有大量实用方法的帮助器类
Facebook SDK for Android 也带来一些有用的例子,您可以用来作为自己应用程序的起点。
尤其有趣的是核心 Facebook
类和 Facebook Dialog
类,下面将更为详细地介绍它们。核心 Facebook
类封装了对用户进行授权、创建 Facebook 对话框、发出 API 请求、注销用户以及获得或设置访问和会话信息及状态的方法。Facebook Dialog
类实现了一个 WebView 及其创建它的方法以及用于处理 Facebook URL(状态)响应的逻辑。SDK 操作离不开对话框。SDK 提供两种方法进行身份认证,一种称之为单点登录,如果安装了的话,它使用原生的 Facebook 应用程序对话框,另一种是默认的 WebView 方法。本文我将重点介绍 WebView 方法。其余 SDK 类是帮助器类,用于封装错误信息或者提供整个 SDK 中使用的有用工具。
下面几节着重介绍一个典型 Facebook 应用程序的用例:
- 安装 Facebook SDK for Android
- 注册您的应用程序
- 创建 SampleApp
- 显示 Facebook 对话框
- 对用户进行授权
- 发出 API 请求
您必须下载并安装 Eclipse 或者您喜欢的 IDE。此外,还必须安装 Android SDK。有关如何下载并安装 Eclipse 和 Android SDK 的信息,请参见 Android Developer 网站(参见 参考资料)的 Download the Android SDK 页面。
Facebook SDK for Android 宿主在 github 的 facebook / facebook-android-sdk 仓库中。下载 SDK 源文件,将之解压到您的工作目录。启动 Eclipse,通过选择 File Menu -> New -> Project 创建一个 Android Project,并选中 Android Project。从 existing source
创建项目,并指向解压的源文件目录(参见 下载 获得源代码)。
在开始之前,您必须注册您的 Facebook 应用程序并得到一个应用程序 ID (client_id
) 和相关的密钥 (client_secret
)。在进行不同的 Facebook API 调用时,会在您的应用程序中使用客户机 ID。
样例应用程序(我将之简称为 SampleApp)展示了如何使用 Facebook SDK for Android。此应用程序包含单个文件,该文件实现 SampleApp 活动,使用一个屏幕来显示消息、Facebook 好友列表,以及用于登录/身份认证用户、获得好友列表和发布到已通过身份认证用户 (me
) 涂鸦墙的菜单项。
在开始之前,请记住您必须像前面解释的那样将您的应用程序注册到 Facebook,还必须将 SampleApp.java 中的属性 APP_ID
设置为由 Facebook 提供的 client_id
(参见 清单 1 )。
// Set application ID to your registered app client_id // See http://www.facebook.com/developers/createapp.php public static final String APP_ID = ".....";
对于 Sample Application 屏幕,使用一种线性布局,包含一个 TextView(用于简单状态消息)、一个 ListView(用于显示从服务器检索到的 Facebook 好友列表)和一些菜单项(用于登录/身份认证用户、获得好友列表和发布到已通过身份认证用户 (me) 的涂鸦墙)。清单 2 展示了主 UI 屏幕布局的 XML UI 声明。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/black" > <TextView android:id="@+id/txt" android:text="@string/hello" android:textColor="@drawable/white" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingRight="10dp" android:paddingLeft="10dp" android:layout_margin="10dp" android:textSize="10sp" android:layout_marginTop="5px" android:layout_marginBottom="5px" android:layout_marginRight="0px" android:layout_marginLeft="0px" android:gravity="left" /> <ListView android:id="@+id/friendsview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textFilterEnabled="true" /> <TextView android:id="@id/android:empty" android:layout_width="match_parent" android:layout_height="match_parent" android:text="No data" /> </LinearLayout>
清单 3 展示了 ListView 中每一行的 XML UI 声明。
<?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="?android:attr/listPreferredItemHeight" android:padding="10dip" > <TextView android:id="@+id/rowtext_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" /> </LinearLayout>
清单 4 展示了菜单项的 XML UI 声明。
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/login" android:title="Login"/> <item android:id="@+id/getfriends" android:title="Get Friends"/> <item android:id="@+id/wallpost" android:title="Wall Post" /> </menu>
图 1 展示了 SampleApp 在登录之前(带有 Login 按钮)和之后(带有 Logout、Get Friends 和 Wall Post 按钮)XML UI 声明的结果。
SampleApp onCreate()
方法在创建 SampleApp 实例时由 Android 平台调用。此方法执行一个基本的检查(以确保在继续之前已经设置了 App ID)、初始化 UI 资源和初始化 Facebook 会话实例(参见 清单 5 )。
/** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make sure the app client_app has been set if (APP_ID == null) { Util.showAlert(this, "Warning", "Facebook Application ID must be set..."); } // Initialize the content view setContentView(R.layout.main); // Get the status text line resource mText = (TextView) SampleApp.this.findViewById(R.id.txt); // Setup the ListView Adapter that is loaded when selecting "get friends" listView = (ListView) findViewById(R.id.friendsview); friendsArrayAdapter = new FriendsArrayAdapter(this, R.layout.rowlayout, friends); listView.setAdapter(friendsArrayAdapter); // Define a spinner used when loading the friends over the network mSpinner = new ProgressDialog(listView.getContext()); mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE); mSpinner.setMessage("Loading..."); // Initialize the Facebook session mFacebook = new Facebook(APP_ID); mAsyncRunner = new AsyncFacebookRunner(mFacebook); }
应用程序流的其余部分通过菜单项由 UI 交互触发。定义了三个菜单项:1) login/logout(切换),2) get friends 和 3) post to the wall,如 清单 4 所示。当用户选择一个菜单项时,应用程序就执行一个适当的操作。下面的清单展示了菜单项是如何处理的。清单 6 展示了如何通过具体化其 XML 定义而实例化菜单的。
/** * Invoked at the time to create the menu * @param the menu to create */ @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); return true; }
清单 7 展示了菜单项在显示之前是如何被修改的,就是说,根据实际情况显示适当的 "login" 或 "logout" 状态并启用/禁用 "get friends" 和 "post to wall"。
/** * Invoked when preparing to display the menu * @param menu is the menu to prepare */ @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem loginItem = menu.findItem(R.id.login); MenuItem postItem = menu.findItem(R.id.wallpost); MenuItem getfriendsItem = menu.findItem(R.id.getfriends); if (mFacebook.isSessionValid()) { loginItem.setTitle("Logout"); postItem.setEnabled(true); getfriendsItem.setEnabled(true); } else { loginItem.setTitle("Login"); postItem.setEnabled(false); getfriendsItem.setEnabled(false); } loginItem.setEnabled(true); return super.onPrepareOptionsMenu(menu); }
清单 8 展示了菜单项是如何被处理的,以及适当的操作(login/logout、get friends、post to wall)是如何被调用的。
/** * Invoked when a menu item has been selected * @param item is the selected menu item */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Login/logout toggle case R.id.login: // Toggle the button state. // If coming from login transition to logout. if (mFacebook.isSessionValid()) { AsyncFacebookRunner asyncRunner = new AsyncFacebookRunner(mFacebook); asyncRunner.logout(this.getBaseContext(), new LogoutRequestListener()); } else { // Toggle the button state. // If coming from logout transition to login (authorize). mFacebook.authorize(this, PERMISSIONS, new LoginDialogListener()); } break; // Wall Post case R.id.wallpost: // Wall Post mFacebook.dialog(SampleApp.this, "stream.publish", new WallPostDialogListener()); break; // Get Friend's List case R.id.getfriends: // Wall Post // Get the authenticated user's friends mSpinner.show(); mAsyncRunner.request("me/friends", new FriendsRequestListener()); break; default: return false; } return true; }
应用程序使用很多回调来处理每个异步调用的状态。SampleApp 定义一个回调来处理 login 请求、logout 对话框、post to wall 对话框和 get friends 请求的成功或失败。您可以利用这个样例应用程序,并添加您自己的操作,遵循添加菜单和相应 Facebook 调用的相同模式,利用对应的回调来接收状态信息。
login 和 post to wall 菜单项都调用 Facebook 对话框(在默认情况下,如果没有定义单点登录选项,此对话框使用 SDK 基于 WebView 的对话框)。下一节将介绍此内容。
FriendsRequestListener
回调在 发出 Facebook API 请求 一节中介绍。最后一个回调是 MyDialogListener
,它实现 Facebook SDK for Android DialogListener
,这用于使用 SDK 基于 WebView 的对话框的 Facebook 请求,下一节中将会介绍。DialogListener
的实现者必须实现适当的完成逻辑;例如,这在 login 和 wall post 请求过程中使用。
对于诸如用户授权、分配权限和消息发布之类的用户交互,Facebook SDK for Android 依赖于 Facebook 基于 web/服务器的对话框。核心 SDK Facebook.java
类在为请求操作产生 UI 对话框时定义方法 dialog()
(参见 清单 9 )。
/** * Generate a UI dialog for the request action in the given Android context * with the provided parameters. */ public void dialog( Context context, String action, Bundle parameters, final DialogListener listener) { : : }
此异步方法接受应用程序上下文的输入参数、执行的操作(比如 login
、publish_stream
、read_stream
、offline_access
)、特定请求或操作需要的参数和异步方法完成执行时调用的侦听器方法。该方法创建适当的 WebView 对话框。例如,要发布一个状态消息,需要调用核心 Facebook 类方法 dialog()
,传递操作 stream.publish
(参见 清单 10 )。
package com.myapp.facebook.android; : import com.facebook.android.*; : mFacebook = new Facebook(); // Facebook core : // Create a Facebook dialog (using the call asynchronous API) mFacebook.dialog( this, "stream.publish", new MyDialogListener()); : : // // My asynchronous dialog listener // public class MyDialogListener extends com.facebook.android.Facebook.DialogListener { public void onComplete(Bundle values) { final String postId = values.getString("post_id"); if (postId != null) { // "Wall post made..." } else { // "No wall post made..." } } public void onFacebookError(FacebookError e) {...} public void onError(DialogError e) {...} public void onCancel() {...} }
该调用的结果是 Facebook 基于 web 的 publish to wall 对话框,如 图 2 所示。
这是熟悉的发布到用户涂鸦墙的 Web 页面,与 Facebook 提供的一样。用户可以跳过或者继续前进并发布消息。这种在同一移动应用程序中混合使用原生和 web 内容是混合应用程序强大之处的很好示例。
Facebook Platform 对 OAuth 2.0 身份认证提供支持,也支持一种较老的、定制的授权签名方案。编写新应用程序时应该避免使用老的身份认证方案,因为对这种老方案的支持很快就会取消了。更多有关 OAuth 的信息,请参见 参考资料 中的 OAuth 2.0 Protocol 规范。
Facebook SDK for Android 协同 Facebook Platform 一起,隐藏了 OAuth 身份认证的复杂性,如 图 3 所示。
图 3. OAuth 2.0 Protocol (IETF)
Facebook SDK for Android 采用移动 web 身份认证方法,而不是采用原生方法。注意,未来版本的 SDK 有可能对 OAuth 提供原生的 Android 支持。对于此方法,SDK 在 WebView 中使用 Facebook 基于 web 的身份认证对话框。这是一个有趣的方法,理由如下:
- 它减少了对应用程序实现 OAuth 原生功能的复杂性。
- 更为重要的是,它通过显示跟在常规浏览器上使用 Facebook 时看到的相同的标准而熟悉的登录和分配权限对话框,赢得用户的信任。
该方法的一个优点是,它有时可能感觉比纯粹的原生实现要慢一些。为此,SDK 包含一个备选的身份认证/登录方法,即使用原生 Facebook 应用程序的单点登录。这就是说,如果官方 Facebook 原生应用程序安装在手机上,那么 Facebook SDK for Android 可以使用它的身份认证/登录活动。但是要使之工作,您必须首先签署您的应用程序(参见 参考资料 中 Frank Ableson 的文章 “Introduction to Android Security”),然后生成一个签名或密钥散列(参见 清单 11 )。
keytool -exportcert -alias [alias] -keystore [keystore] | openssl sha1 -binary |
openssl base64
注意, 清单 11 中的代码通常在一行中。这里出于格式化目的,将它分成了多行。
然后您必须在 图 4 所示 mobile and devices 部分下面(查看 图 4 的 大图),为您的特定应用程序注册 Facebook 上生成的密钥散列。
一旦注册了,您就必须为您的应用程序定义一个 “活动结果处理程序”;实现 onActivityResult(...)
(您必须在它上面调用方法 facebook.authorizeCallback(...)
,如 清单 12 所示)。
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); facebook.authorizeCallback(requestCode, resultCode, data); : : // ... Other onActivityResult steps per your app... }
注意,如果没有定义单点登录方法,或者没有给出原生 Facebook 应用程序,那么 SDK 将默认对身份认证/登录使用 WebView 方法。本文其余部分将着重介绍这种默认方法。
正如前面所提到的,默认情况下,应用程序对用户简介中的所有公共数据具有访问权限。要访问私有数据,应用程序必须请求权限,并由用户对应用程序授予权限,才能进行访问。获得对私有数据进行访问的权限被称作扩展权限。
Facebook SDK for Android authorize()
方法实现 OAuth 2.0 User-Agent 流,以检索一个访问令牌,用于后续的 API 请求中。该方法开始一个活动(原生的 Facebook 应用程序,如果给出并配置了的话)或者一个 WebView 对话框,以提示用户输入凭证(身份认证)和权限(授权),参见 清单 13 )。
/** * Authorize method that grants custom permissions. */ public void authorize(Activity activity, String[] permissions, final DialogListener listener) { : : }
注意,为了单点登录身份认证正确工作,您必须在 onActivityResult()
函数中包含一个对 authorizeCallback()
方法的调用。
回想一下 清单 8 中登录菜单项是如何利用权限调用 authorize()
方法的。
清单 14 展示了如何利用权限调用 authorize()
方法,以写入内容。它也具有权限来写评论和喜好(publish_stream
)、阅读用户的提要、执行搜索(read_stream
)和让访问凭证长期有效(offline_access
)。不要忘记设置您的 APP_ID
。
package com.myapp.facebook.android; : import com.facebook.android.*; : public static final String APP_ID = "13234..."; private static final String[] PERMISSIONS = new String[] {"publish_stream", "read_stream", "offline_access"}; : : // Call the authorization method mFacebook.authorize( getContext(), APP_ID, mPermissions, new MyLoginDialogListener()); : : // Asynchronous Callback when authorization completes private final class MyLoginDialogListener implements com.facebook.android .Facebook.DialogListener { public void onComplete(Bundle values) {...} // here enable logout public void onFacebookError(FacebookError error) {...} public void onError(DialogError error) {...} public void onCancel() {...} }
authorize()
方法在内部调用前面介绍过的 dialog()
方法,但是这一次它传递一个针对操作的 Login 请求。在 Facebook Platform 及其 OAuth 实现的帮助下,authorize()
方法也处理到 Facebook 的身份认证请求,并返回整个 Facebook 会话和 API 调用期间使用的 access_token:https://graph.facebook.com/ID?access_token=...
。
有关身份认证如何工作的详细信息,请参见 参考资料 中的 Facebook Authentication 页面。
调用 authorize()
方法导致 图 5 中基于 WebView 的对话框。
用户登录之后,会被提示按照应用程序的请求输入权限(email 或电话信息和密码)。用户可以允许或拒绝应用程序权限访问她的 Facebook 和执行如下操作:访问基本信息、发布到用户的涂鸦墙、访问 News Feed 中的帖子或者访问用户数据。
核心 Facebook 类为 Old REST 和 Graph API 调用实现很多 request()
方法。此外,SDK 提供帮助器封装器类来异步地发出核心请求 API 调用。
作为一个 API 请求的例子,您将发出一个请求,为经过身份认证的用户检索好友。回想一下 Graph API 的结构:
https://graph.facebook.com/ID/CONNECTION_TYPE
另外,回想一下特殊的 ID me
,它用于识别经过身份认证的用户,此用户已经登录:https://graph.facebook.com/me/friends
。
清单 15 展示了一个来自 清单 8 的代码片段,即如何实现 request()
方法调用。在本例中,您使用 AsyncFacebookRunner.request(...)
方法,这是一个帮助器封装器方法,它通过运行在自己的线程中,使得底层的请求方法是异步的。这一步是为了避免阻塞主 UI 线程。
// Get Friend's List case R.id.getfriends: // Wall Post // Get the authenticated user's friends mSpinner.show(); mAsyncRunner.request("me/friends", new FriendsRequestListener()); break;
FriendsRequestListener onComplete(...)
回调在取得好友列表的请求执行完成时被调用。该方法解析返回的好友列表 JSON。注意, 清单 16 并没有展示所有实现的方法。
/** * FriendsRequestListener implements a request lister/callback * for "get friends" requests */ public class FriendsRequestListener implements com.facebook.android.AsyncFacebookRunner.RequestListener { /** * Called when the request to get friends has been completed. * Retrieve and parse and display the JSON stream. */ public void onComplete(final String response) { mSpinner.dismiss(); try { // process the response here: executed in background thread Log.d("Facebook-Example-Friends Request", "response.length(): " + response.length()); Log.d("Facebook-Example-Friends Request", "Response: " + response); final JSONObject json = new JSONObject(response); JSONArray d = json.getJSONArray("data"); int l = (d != null ? d.length() : 0); Log.d("Facebook-Example-Friends Request", "d.length(): " + l); for (int i=0; i<l; i++) { JSONObject o = d.getJSONObject(i); String n = o.getString("name"); String id = o.getString("id"); Friend f = new Friend(); f.id = id; f.name = n; friends.add(f); } // Only the original owner thread can touch its views SampleApp.this.runOnUiThread(new Runnable() { public void run() { friendsArrayAdapter = new FriendsArrayAdapter( SampleApp.this, R.layout.rowlayout, friends); listView.setAdapter(friendsArrayAdapter); friendsArrayAdapter.notifyDataSetChanged(); } }); } catch (JSONException e) { Log.w("Facebook-Example", "JSON Error in response"); } } : : }
根据您的应用程序的要求,来自 Facebook 服务器的响应(JSON 格式)必须相应地被解析和处理。您可能决定通过使用 WebView 或者跟本 SampleApp(参见 图 6 )中一样使用 ListView 显示这样的信息。
在本文中,您学习了 Facebook API。首先是 Facebook Platform 及其 API 的一般概述,然后是 Facebook SDK for Android 和一个样例应用程序。学习本文之后,您更好地了解了各种不同的 Facebook API 以及如何开始为 Android 平台编写 Facebook 应用程序。
出处: http://wangkewei.cnblogs.com/
版权声明: 本文的版权归作者与博客园共有。转载时须注明本文的详细链接,否则作者将保留追究其法律责任的权利。
您可以从这里更方便的找到我的文章。