65.9K
CodeProject 正在变化。 阅读更多。
Home

Android 应用中社交网络集成的初学者指南:与 Twitter 和 Facebook 合作

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2014 年 10 月 6 日

CPOL

20分钟阅读

viewsIcon

47533

downloadIcon

2585

Android 中社交网络集成的简单分步指南

目录

1. 背景

2. Android Twitter 集成

       2.1 设置 Twitter API

       2.2 Twitter 集成的 Android 应用设置

       2.3 应用布局

       2.4 使用 oAuth 进行身份验证

       2.5 oAuth 代码使用

       2.6 获取内容

       2.7 发布推文

3. Facebook 集成

       3.1 在 Eclipse 中生成密钥库

       3.2 在 Facebook 中创建和验证应用

       3.3 将 Facebook SDK 集成到你的项目中

       3.4 Facebook SDK 代码使用

                      3.4.1 身份验证 

                      3.4.2 发布到动态

                      3.4.3 从 Facebook 提取信息

4. 快速解决方案:使用 Android 的 Intent

5. 结论

 

1. 背景

 

如果你是一名有抱负的 Android 应用开发者,那么你应该学习的第一件事就是应用的社交网络集成。事实上,用户非常喜欢在社交网络上分享他们在应用中获得的分数、编辑过的照片或完成的任务。如果你正在开发一个“步行应用”,用户会喜欢分享他们走过的距离。如果你正在开发一个卡路里计算应用,那么分享一个超重者减掉了多少卡路里对用户来说总是很直观的。

但是,社交集成不仅限于应用用户的愉悦感或只是应用的另一个功能。它极大地提高了应用的可见性,并通过社交网络帮助你推广你的应用。换句话说,这是应用的免费广告。

尽管有许多关于 Android 平台社交集成的教程和“操作方法”,但我还没有找到任何一篇文章能够从一个单一的界面详细介绍 Twitter 和 Facebook。

在本教程中:

1) 我们将学习 Twitter 集成和获取推文

2) 我们将学习 Facebook 集成和访问 Facebook 的内容

3) 我们将最终应用我们的意见挖掘技术来分析内容,告诉用户内容的积极性。

 

2. Android Twitter 集成

Twitter 是一个最令人惊叹且功能强大的社交网络,它赋予了人们前所未有的权力。客户可以发布他们的投诉,粉丝可以向他们的明星发送加油和祝福信息,人们可以公开批评公众人物和政府官员,相关人员可以从推文中了解民众的情绪。因此,我们将学习如何从我们的应用发布推文,以及通过我们的账户从 Twitter 获取内容。

2.1 设置 Twitter API

Twitter 与大多数社交网络和热门网站一样,使用 128 位 SSL 加密数据。因此,与服务器之间的数据交换是安全的。因此,与 Twitter 合作需要 Twitter 对应用进行身份验证。此身份验证与应用开发者的账户绑定。

所以第一步是创建一个新应用并授予它必要的权限。打开以下地址:

https://dev.twitter.com/apps/new

图 2.1 Twitter 中的新应用注册

填写具有唯一应用名称的表单。网站和回调网站应与您的网站地址相同。另外一点要确保的是 URL 字段必须以“http://”开头。

如果您没有网站,您可以创建一个Blogger 博客,只需大约两分钟。虽然我强烈建议您拥有自己的网站。如果您想认真对待应用开发,这确实是一个重要的要求。

2.2 Twitter 应用创建成功

如您所见,默认情况下,应用创建时具有只读访问权限。您需要点击修改应用权限链接,并将权限更改为读、写和访问直接消息 。如果您的应用不发布任何内容,您可以保持原样。在大多数情况下,读写权限就足够了,应用无需访问直接消息。用户实际上讨厌那些尝试这样做的应用。但这是一个学习应用,我们将尝试所有选项。

图 2.3:更改应用权限

更新权限后,就可以获取密钥了。点击 API 密钥选项卡,您将看到密钥。(注意:出于安全原因,请勿公开分享您的 API 密钥和密钥

图 2.4 Twitter 应用 API 密钥生成中的 API 密钥选项卡

 

在成功满足了初步要求后,是时候进入我们的 Android 平台并将 Twitter 应用集成到 Android 中了。

2.2 Twitter 集成的 Android 应用设置

幸运的是,有一个很棒的 Java 平台 Twitter 操作库,名为 **Twitter 4j**。它几乎可以用于所有 Java 平台,如 Swing、Applet,当然还有 Android。从这里>>下载该库。

在 Eclipse 中创建一个名为 SocialIntegration 的 Android 应用(您可以使用任何您喜欢的项目名称。由于本教程中使用 SocialIntegration,因此使用此项目名称可能会让步骤稍微容易一些),并将 Twitter 4j Core 库拖放到您项目的 lib 文件夹中,如下图 2.5 所示。

图 2.5:在 Android 项目中设置 Twitter 4j 库

现在,您可以进入 MainActivity.java 的导入部分,输入 **import twitter4j;**。如果一切正常,您将看到 twitter4j 包中的一列包。

2.3 应用布局

图 2.6 充分说明了我们应用的目标。a) 我们将提供一个登录按钮,该按钮应触发身份验证过程。一旦身份验证成功,用户就可以从应用发布推文。他还可以搜索 Twitter 中的某个词,结果会显示在 ListView 中。

图 2.6 Twitter 集成的应用布局

您可以设计布局,因为所有变量(控件)都可以在右上角面板中看到。另一方面,您可以使用以下现成的 XML 布局文件来快速拥有自己的布局。如果您正在复制 XML,请不要忘记清理并构建您的项目。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.integratedideas.socialintegration.MainActivity$PlaceholderFragment"
    tools:ignore="HardcodedText" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_marginTop="10dp"
        android:layout_below="@+id/edSearch" >
        
    </ListView>

    <EditText
        android:id="@+id/edPublish"
        android:layout_width="match_parent"
        android:layout_marginRight="80dp"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/btnLoginNPublish"
        android:layout_alignLeft="@+id/edSearch"
        android:ems="10" >

        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/edSearch"
        android:layout_width="match_parent"
        android:layout_marginRight="80dp"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/listView1"
        android:layout_below="@+id/edPublish"
        android:layout_marginTop="17dp"
        android:ems="10" />

    

    <TextView
        android:id="@+id/tvMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignRight="@+id/edPublish"
        android:layout_marginRight="64dp"
        android:layout_marginTop="14dp"
        android:text="TextView" />

    <Button
        android:id="@+id/btnSearch"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/listView1"
        android:layout_alignRight="@+id/btnLoginNPublish"
        android:text="Search" />

    <Button
        android:id="@+id/btnLoginNPublish"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tvMessage"
        android:layout_toRightOf="@+id/tvMessage"
        android:text="Login" />

</RelativeLayout>

我们还将保持 edSearch、edPublish、btnSearch 在登录前不可见,并在登录后更改它们的可见性。其次,一旦登录成功,我们将把 btnLoginNPublish 的文本从初始文本“login”更改为“publish”。但这一切都通过代码完成。

首先,即身份验证应用并提取用户信息。

2.4 使用 oAuth 进行身份验证

为了理解身份验证如何工作,您应该首先查看图 2.7。它将阐明身份验证的概念。

图 2.7 Twitter 应用身份验证的序列图

图 2.7 是对包括 Twitter 和 Facebook 在内的任何社交网站应用进行身份验证的通用序列图。

所以让我们来理解我们将要做什么:我们将首先在我们的主应用中构建一个 URL,其中包含调用 Twitter 身份验证的 URL,该 URL 使用我们在图 2.4 中获得的 ApiSecret 和 ApiKey 进行解析,然后启动一个浏览器活动。

该浏览器页面将询问用户是否要授权该应用,如果用户同意,则将 URL 传递给 Twitter 服务器,Twitter 服务器成功验证 ApiKey 和 ApiSecret 以及通过浏览器 cookie 提取的用户凭据后,将返回访问令牌和访问密钥。如果用户尚未登录 Twitter,则会提示其输入用户名和密码,并且新提交的 URL 包含 api 密钥、api 密钥、用户名和密码。显然,由于 Twitter 使用 SSL,所有数据将在提交前被加密,因此可以认为足够安全。

一旦 AccessToken 或 Simple Token 从服务器返回到浏览器,它会附带一个用于重定向的简单 JavaScript,该 JavaScript 会强制应用使用包含 Access Token 和 Access Secret 的新数据重新加载。

现在,应用使用此令牌以及通过访问令牌获得的用户 ID 来进一步请求推文或进行发布。

2.5 oAuth 代码使用

您应该已经从我们 Android 数据处理教程的从 Web 获取数据部分了解了,要访问 Internet,您必须通过 Manifest 提供 INTERNET 权限。

因此,在您的 AndroidManifest.xml 的 <application> 标签之前添加以下两行:

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

现在我们也知道网络相关的操作不允许在主线程中进行。为了解决这个问题,我们需要使用 AsyncTask。但是为了简单起见,我将通过在 `onCreate` 方法中调用 `super` 后添加以下代码行来 hack 它,以便您的应用可以访问网络操作。

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

让您的 MainActivity 类实现 OnClickListener。将按钮的点击监听器设置到重写的 `onClick` 方法中。在 `onClick` 方法中,使用 Executor 调用 Twitter 登录方法。

@Override
    public void onClick(View v) 
    {
    

        Button b=(Button)v;
        if(b.getText().toString().trim().equals("Login"))
        {
        Executor exe=new Executor()
        {
            
            @Override
            public void execute(Runnable command) 
            {
                
                // TODO Auto-generated method stub
                try
                {
                   
                     
                //loginToTwitter();
                 MyTwitterLogin();
                }
                catch(Exception ex)
                {
                    Log.i("Exception:",ex.getMessage());
                    
                }
                
            }
        };
        exe.execute(null);
        }
         
        
    }

以下是 **MyTwitterLogin()** 方法:

static final String TWITTER_CALLBACK_URL = "oauth://t4jSample";
static String PREFERENCE_NAME = "twitter_oauth";
static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
static final String PREF_KEY_OAUTH_SECRET = "oauth_token_secret";
static final String PREF_KEY_TWITTER_LOGIN = "isTwitterLogedIn";
static final String URL_TWITTER_AUTH = "auth_url";
static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
static final String URL_TWITTER_OAUTH_TOKEN = "oauth_token";

public void MyTwitterLogin()
     {
         try {
             twitter.setOAuthConsumer(ApiKey, ApiSecret);
             requestToken = twitter
                     .getOAuthRequestToken(TWITTER_CALLBACK_URL);
             MainActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
                     .parse(requestToken.getAuthenticationURL())));
             
             Log.i("Request Toke.....=>",requestToken.toString());
             
            // twitter.setOAuthAccessToken(requestToken.getToken());

         } 
         catch (Exception e) 
         {
             Log.i("In getting Authentication",e.getMessage());
         }

         
     }

其中 ApiKey 和 ApiSecrets 是您从 Twitter 应用设置中获得的(参见图 2.4)。其他参数不得更改。请注意,我们正在启动一个 Intent,该 Intent 理想情况下会显示您的浏览器以及身份验证选项,如下图 2.9 所示,当点击登录按钮时(如图 2.8 所示)。

图 2.8:应用的初始屏幕

图 2.9:点击登录按钮后触发的身份验证 URL

另请参阅图 2.10 中的请求令牌结构。这是 Twitter 响应的依据。

图 2.10:在图 2.9 的 URL 中传递的请求令牌

用户身份验证应用后,浏览器将显示身份验证成功,同时会再次打开主活动。

图 2.11:身份验证成功后的浏览器

重定向后,您的应用将重新加载,但其数据中会包含响应令牌。因此,当应用加载时,哪个方法会被调用?显然是 `onCreate`。因此,在 `onCreate` 方法中,我们将添加一个 if 循环,该循环在 MainActivity 的数据中包含响应令牌时触发。

 Uri uri = getIntent().getData();
if(uri!=null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) 
            {

                uri = getIntent().getData();

            //URL_TWITTER_OAUTH_TOKEN
       final       String verifier = uri.getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);
       final       String token = uri.getQueryParameter(URL_TWITTER_OAUTH_TOKEN);

                try {
                    
                    


                    MainActivity.this.accessToken = twitter.getOAuthAccessToken(requestToken, verifier);

                    long userID = accessToken.getUserId();
                    User user = twitter.showUser(userID);
                    uname = user.getName();
                    screenName=accessToken.getScreenName();
                    
                
                   // Log.i(uname+" "+userID+" "+accessToken.getScreenName(),response.getText());
                    tvMessage.setText("Welcome "+uname+"("+screenName+")");
                    
                    btnLoginNPublish.setText("Publish");
                    edSearch.setVisibility(View.VISIBLE);
                    edPublish.setVisibility(View.VISIBLE);
                    btnSearch.setVisibility(View.VISIBLE);
                    
                    
                   }
                catch(Exception ex1)
                {
                    
                    Log.i("Fetching Access token Error",ex1.getMessage());
                }

正如您从 `requestToken` 和 `verifier`(来自 Twitter 服务器的响应)中可以看到的,我们构建了一个 `accessToken`。此令牌包含所有用户相关信息。我们提取信息,然后使其他表单组件可见。

图 2.12:身份验证成功后的表单

其他初始化如下:

       listView1=(ListView)findViewById(R.id.listView1);
        tvMessage=(TextView)findViewById(R.id.tvMessage);
        edSearch=(EditText)findViewById(R.id.edSearch);
        tvMessage.setText("Please Login ");
        btnLoginNPublish=(Button)findViewById(R.id.btnLoginNPublish);
        btnLoginNPublish.setOnClickListener(this);
        btnLoginNPublish.setText("Login");
        
        btnSearch=(Button)findViewById(R.id.btnSearch);
        btnSearch.setOnClickListener(this);
        
        
        edPublish=(EditText)findViewById(R.id.edPublish);
        
        
        if(twitter==null)
        twitter = new TwitterFactory().getInstance();
        
        edSearch.setVisibility(View.INVISIBLE);
        edPublish.setVisibility(View.INVISIBLE);
        btnSearch.setVisibility(View.INVISIBLE);
    

请记住,所有这些都必须出现在“if 循环”之前。否则,重定向后您将收到 NullPointerException,因为任何控件都不会被初始化。

 

更新

在处理此概念时,我意识到这种 oAuth 方法存在一些小问题。当我们尝试将此概念纳入其他应用时,Twitter 不会正确重定向。为了避免这个问题,请在您的 AndroidManifest.xml 中 MainActivity 的 intent-filter 之后添加以下 intent 过滤器:

<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="x-oauthflow-twitter" android:host="callback" />
            </intent-filter>

现在将 Callback URL 更改为:

 static final String TWITTER_CALLBACK_URL = "x-oauthflow-twitter://callback";

这应该可以解决重定向问题。

2.6 获取内容

我提供了一个简单的搜索选项。您可以搜索主题或用户名,它会显示所有结果。您需要做的就是传递一个查询字符串并调用搜索方法。搜索方法返回一个 **Status** 类的列表,其中每个 status 都包含推文、转推计数、收藏计数、提及、推文创建日期/时间等。我将使用一个简单的 StringArrayAdapter 来获取 status 并将其分配给列表框。您可以使用复杂 ListView 的概念来更愉快地呈现信息。

if(b.getText().toString().trim().equals("Search"))
          {
              ArrayList<String>tweetString=new ArrayList<String>();
              try{
              Query query = new Query(edSearch.getText().toString().trim());
              List list = twitter.search(query).getTweets();
              
              for (int i=0;i<list.size();i++)
              {

                  twitter4j.Status each = (twitter4j.Status) list.get(i);
                  tweetString.add(each.getUser().getScreenName()+":" + each.getText()+" [Retweet:"+each.getRetweetCount()+", Favourites: "+ each.getFavoriteCount()+"]");
            
              }
              String [] tweets=tweetString.toArray(new String[1]);
              ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                        android.R.layout.simple_list_item_1, tweets);
            
            listView1.setAdapter(adapter);
              }catch(Exception ex)
              {
                  
              }
              
          }

图 2.13:搜索结果

2.7 发布推文

您可以通过调用 **updateStatus** 方法并以最简单的形式传递字符串来发布推文。

if(b.getText().toString().trim().equals("Publish"))
          {
             try{
                 StatusUpdate su=new StatusUpdate("");
                 su.
              twitter4j.Status response = twitter.updateStatus(edPublish.getText().toString());
              alert.showAlertDialog(this, "Posting Successfull", "Your Tweet is Posted In your Timeline", true);
             }catch(Exception ex)
             {
                 alert.showAlertDialog(this, "Posting Successfull", ex.getMessage(), false);
             }
          }

但是,如果您打算开发一个更完整的 Twitter 应用,那么您应该使用 StatusUpdate 对象。它提供了很多字段,包括回复其他推文的选项等等。图 2.15 显示了一些重要可能性。

图 2.14:状态更新成功(发布推文)

下载 SocialIntegration_TWITTER_PART.zip 并玩转这个应用。

在成功完成 Twitter 部分后,是时候研究 Facebook 集成技术了。

3. Facebook 集成

Facebook 集成比 Twitter 集成要棘手一些。Facebook 要求一个**签名应用**与其联系以进行授权。因此,集成并不直接。首先,您需要在 Eclipse 中生成一个密钥库,然后用该密钥库签名您的应用。您需要在注册您的应用到 Facebook 时提供签名密钥。因此,我们将首先从 Eclipse 获取密钥库,然后用它来签名您的应用。

3.1 在 Eclipse 中生成密钥库

点击 **Windows->Preferences->Debug**,如下所示。

图 3.1 在 Eclipse 中定位密钥库位置

记下默认调试密钥库的路径。现在打开您的命令提示符。您需要两个工具来为 Eclipse 生成密钥:1)**keytool** 2)**openssl**

keytool 始终位于您 Java 安装的 jre 目录中。如果 Java 的类路径已添加到您的系统中,那么您应该可以从任何地方访问它。

首先在命令提示符中输入 **keytool** 并回车。如果看到“命令未找到”,那么您需要手动更改到 jre 目录。现在输入 keytool 命令,您将看到它的用法。

图 3.2:定位并切换到 keytool 所在的 jre 目录。

您需要的下一个工具是 openssl。再次输入命令 **openssl**。如果您的命令提示符再次显示“命令未找到”,那么您需要从这里下载 openssl 软件>>

将 zip 文件解压到任何目录,但最好选择一个您可以记住的目录用于未来的工作。

现在在命令提示符中输入以下命令:

引用

keytool -exportcert -alias androiddebugkey -keystore C:\Users\Rupam\.android\debug.keystore | E:\openssl-0.9.8k_WIN32\bin\openssl
 sha1 -binary | E:\openssl-0.9.8k_WIN32\bin\openssl base64

其中粗体部分是您的密钥库位置,如图 3.1所示,下划线部分 E:\openssl-... 是您刚下载的 openssl 的完整路径。输入并回车命令后,它会要求您输入密码。输入一个您可以记住的密码。这将在您签名应用以发布到 Google Play 时有所帮助。

图 3.3 为 Eclipse 生成密钥

生成密钥后,让我们直接进入在 Facebook 中创建和验证应用。

3.2 在 Facebook 中创建和验证应用

打开

https://developers.facebook.com/

在“应用”部分选择“创建新应用”。

图 3.4 选择在 Facebook 中创建新应用

选择 Android。

图 3.5 创建具有新应用 ID 的新 Android 应用

完成所有步骤。您将看到以下屏幕,其中包含将应用安装到模拟器以及将 SDK 导入您的应用的所有分步指南。

**从本页提到的链接下载 SDK。**  Facebook 经常更改其 API、访问技术等。因此,本教程不提供任何 SDK 链接。下载最新版本总是明智的,该版本始终可以在此页面上找到。

图 3.6 在 Facebook 中创建新应用后的屏幕,指导用户进行后续操作

我建议您此时不要将 Facebook SDK 导入您的项目。我们只使用其中的一小部分,为此您不需要示例。但如果您想在 Facebook 应用开发方面有所成就,您可以随时将整个 SDK 导入您的 Eclipse 工作区并玩转示例。

 

向下滚动此页面,您将看到该应用正在询问您的 Android 应用包名和活动名。按照下图所示填写。

图 3.7:在 Facebook 应用中填写 Android 项目详细信息

现在,通过图 3.3获得的密钥应提供给下一个屏幕,如下所示:

图 3.8:将 Eclipse 密钥输入 Facebook 应用

为发布版也提及相同的密钥哈希。然后点击下一步。这应该完成了 Facebook 集成所需的所有步骤。

3.3 将 Facebook SDK 集成到你的项目中

实际上有两种方法可以做到:使用 Facebook 建议的方法,即导入 SDK 然后使用示例等。还有一个简单的方法:下载 facebookIntegrationEssentials.zip

解压缩文件夹。您可以看到其中的 src、libs、res 文件夹。将 src/com/facebook 文件夹上传到您 Eclipse 项目的 src 文件夹。将 libs 文件夹中的 jar 文件上传到您项目的 libs 文件夹,并将 res/drawable-xhdpi 文件上传到您项目的相应文件夹,如下图所示:

3.9 为 Facebook 集成做准备

一旦您成功完成这些步骤,您的项目应该看起来与下图类似:

图 3.10:Facebook SDK 集成后的项目视图

清理并构建您的项目,您就可以开始使用 Facebook 了。在下一节中,我们将介绍编码部分。

3.4 Facebook SDK 代码使用

当您进入 Facebook 开发者仪表板并选择您的应用时,您将看到应用 ID,如下所示:

图 3.11:从 Facebook 开发者仪表板看到的 App ID

与 Twitter 不同,我们不需要传递应用密钥来与 Facebook 交互。此 ID 将用于初始化一个 Facebook 类实例,该实例最终用于从 Facebook 发布或获取数据。

private Facebook facebook;
private static final String APP_ID = "YOUR_APP_ID_HERE";
private static final String[] PERMISSIONS = new String[] { "publish_stream","read_stream"};

现在 Facebook 应用需要在身份验证请求时提供权限列表。如果您想知道合适的请求是什么,哪些权限是您已获得的,以及您还可以寻求哪些其他权限,您可以打开 Facebook 的在线 Graph API 测试工具:

https://developers.facebook.com/tools/explorer/145634995501895/?method=GET&path=me%3Ffields%3Did%2Cname&version=v2.1

这是一个很棒的工具,不仅可以测试您的查询,还可以测试您的访问令牌、查询中的字段等。一旦您打开该工具,它就会自动为您获取一个访问令牌。您可以使用该令牌来构建可以放入代码中的查询。

图 3.12:使用 Facebook Graph API 工具资源管理器

在获得了基本知识后,让我们来完成身份验证的代码。

3.4.1 身份验证 

请记住我们图 2.7中的内容:首先,应用会请求一个包含应用 ID 的请求令牌(此处不需要密钥)。Facebook 服务器在验证令牌后将响应一个访问令牌。接收访问令牌会重启表单。因此,我们需要方法来存储令牌。我们可以使用共享首选项来存储令牌。在触发登录之前,我们可以检查是否存在访问令牌,如果存在,则检查其过期时间,然后打开身份验证对话框。在本教程中,我绕过了此逻辑,以便在点击登录按钮时始终打开身份验证对话框!

public boolean saveCredentials(Facebook facebook) {
            Editor editor = getApplicationContext().getSharedPreferences(KEY,
                    Context.MODE_PRIVATE).edit();
            editor.putString(TOKEN, facebook.getAccessToken());
            editor.putLong(EXPIRES, facebook.getAccessExpires());
            return editor.commit();
        }

        public boolean restoreCredentials(Facebook facebook) {
            SharedPreferences sharedPreferences = getApplicationContext()
                    .getSharedPreferences(KEY, Context.MODE_PRIVATE);
            facebook.setAccessToken(sharedPreferences.getString(TOKEN, null));
            facebook.setAccessExpires(sharedPreferences.getLong(EXPIRES, 0));
            return facebook.isSessionValid();
        }

最后,登录方法如下:

public void LoginToFacebook() 
        {
            facebook.authorize(this, PERMISSIONS, Facebook.FORCE_DIALOG_AUTH,new LoginDialogListener());
        }

可以看到,我们传递了一个 `LoginDialogListener` 类的实例,该类是 `MainActivity` 的内部类,它定义了身份验证过程完成后要执行的操作。

最后,我们从 `onClick` 调用此方法以通过 Facebook 验证用户登录。

3.4.2 发布到动态

您可以将消息、照片等发布到您的动态。

public void postToWall(String msg) {
            Log.d("Tests", "Testing graph API wall post");
             try {
                    String response = facebook.request("me");
                    Bundle parameters = new Bundle();
                    parameters.putString("message", msg);
                    parameters.putString("description", "test test test");
                    response = facebook.request("me/feed", parameters, 
                            "POST");
                    Log.d("Tests", "got response: " + response);
                    if (response == null || response.equals("") || 
                            response.equals("false")|| response.contains("error")) {
                       Log.v("Error", response.toString());
                    }
             } catch(Exception e) {
                 e.printStackTrace();
             }
        }

在查询中使用 **/me/feed** 可以发布到您的动态。您还需要将消息作为额外的参数传递。默认情况下,请求类型为“Get”。但在发布时,必须明确指定为“Post”。您也可以从 Facebook Graph API 工具资源管理器测试该查询。

如果一切顺利,您将看到您的应用成功进行了身份验证和发布。

图 3.13:Facebook 动态中的身份验证和发布

3.4.3 从 Facebook 获取信息

图 3.12 清楚地表明,查询结果始终是一个 JSON 对象。因此,您可以使用 JSON 解析响应来获取信息。我提供了一些实用方法,这些方法将有助于您基本了解查询结构。

public void fetchFacebookFriends()
        {
             try {
                    String response = facebook.request("me");
                    
                    response = facebook.request("me/friends");
                    
                    Log.d("Tests", "got response: " + response);
                    if (response == null || response.equals("") || 
                            response.equals("false")|| response.contains("error")) {
                       Log.v("Error", response.toString());
                    }
                    else
                    {
                    
                    
                       
                            JSONObject jsonObject = new JSONObject(response);
                            try {
                             JSONArray array = jsonObject.getJSONArray("data");
                             for (int i = 0; i < array.length(); i++) {
                                 JSONObject object = (JSONObject) array.get(i);
                                 Log.d( "id = "+object.get("id"),"Name = "+object.get("name"));
                                  }
                                 } 
                            catch (JSONException e) 
                               {

                                   e.printStackTrace();
                                  }
                     
                    }
             }catch(Exception ex1)
             {
                 
             }
               }
        public void fetchMyFacebookStatuses()
        {
             try {
                    String response = facebook.request("me");
                    
                    response = facebook.request("me/statuses");
                    
                    Log.d("Tests", "got response: " + response);
                    if (response == null || response.equals("") || 
                            response.equals("false")) {
                       Log.v("Error", response.toString());
                    }
                    else
                    {
                    
                    
                       
                            JSONObject jsonObject = new JSONObject(response);
                            try {
                             JSONArray array = jsonObject.getJSONArray("data");
                             for (int i = 0; i < array.length(); i++) {
                                 JSONObject object = (JSONObject) array.get(i);
                                 Log.d( "Message id = "+object.get("id"),"Message = "+object.get("message"));
                                  }
                                 } 
                            catch (Exception e) 
                               {
                                Log.i("Error in Statuses:",e.getMessage());

                                
                                   
                                  }
                     
                    }
             }catch(Exception ex1)
             {
                 Log.i("Error in Statuses:",ex1.getMessage());
             }
               }

您可以首先在 Graph API 资源管理器中测试您的查询,以设计要作为 JSON 对象标识符传递的字段。另一方面,您也可以使用断点和调试选项来跟踪字段,如下图所示:

图 3.14:字符串响应和 JSON 对象解析

图 3.15 获取用户状态更新

您可以直接使用示例项目并开始集成。

所有获取和发布方法都可以在 `LoginDialogListener` 中进行测试,它是 `MainActivity` 的内部类。在身份验证任务成功完成后,您可以调用这些方法进行测试。此外,您可以根据您的逻辑在代码中使用它们。

class LoginDialogListener implements DialogListener {
        public void onComplete(Bundle values) {
            saveCredentials(facebook);
            showToast( "Login Successfull in Facebook");
            //fetchFacebookFriends();
            //postToWall("Another post from Eclipse...");
             fetchMyFacebookStatuses();
            //fetchFriendsFacebookStatuses();
            
        }

`showToast` 是一个创建简单 Toast 的方法,Toast 只是一个弹出对话框,会在几秒钟后消失。这是一种向用户传达消息的简洁方式。

 private void showToast(String message) 
     {
            Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT)
                    .show();
        }

下载 Testing-Facebook-Integration-App.zip 并测试这些方法。

4. 快速解决方案:使用 Android 的 Intent

这是跨不同平台(包括 Twitter、Facebook、LinkedIn、Gmail、蓝牙等)共享数据的最简单、最有效的方法。此方法既不需要通过网站进行应用身份验证,也不需要任何其他外部库或 JSON。**但是请注意,这仅适用于共享数据,无法使用此方法获取数据。**

 因此,如果您的应用唯一的功能是共享数据(文本、图像),那么就使用此方法。我们将提供两个菜单选项:一个用于浏览图像,另一个用于使用 Android 的 Intent 进行共享。

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res-auto">
  <item android:id="@+id/menuBrowse"
android:title="Browse Photos" />
 
   <item android:id="@+id/menuShare"
android:title="Share" 
android:actionProviderClass=
                "android.widget.ShareActionProvider"/>
   
   
</menu>

相应地,我们需要在 MainActivity 中编写方法来处理新修改的菜单。

正如您所见,我们添加了一个名为“共享”的新菜单项,其中使用了 `ShareActionProvider` 小部件。因此,每当单击此项时,在进入常规菜单处理部分后,都会出现一个该小部件。

现在我们需要处理的不仅是我们主菜单,还要初始化 `ShareActionProvider` 实例并将其关联到菜单选项项。


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        //getMenuInflater().inflate(R.menu.share_menu, menu);
        
         MenuItem item = menu.findItem(R.id.menuShare);
         ShareActionProvider myShareActionProvider = (ShareActionProvider) item.getActionProvider();
            
        return super.onCreateOptionsMenu(menu);        
    }

如果用户选择浏览选项,我们将提供文件选择器 Intent,并收集所选文件的 Uri。

当用户选择“共享”按钮时,我们将首先通过查询 Media content provider 将文件 Uri 转换为绝对路径。将从文件路径创建一个位图图像,并加载到图像视图中。

Uri fileUri=null;
    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
    {
        Intent myIntent;
        switch (item.getItemId()) 
        {
        case R.id.menuShare:
            try{
            Log.d("Ok this is pressed","In the share menu");
            myIntent = new Intent(Intent.ACTION_SEND);
            myIntent.setType("image/jpeg");   
                try{
               myIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
                }catch(Exception ex)
                {
                    
                }
            
                myIntent.putExtra(Intent.EXTRA_SUBJECT, "Sharing Example: Codeproject Tutorial");
                myIntent.putExtra(Intent.EXTRA_TEXT, "Shared SocialIntegration app written by Rupam Das");
                
                startActivity(Intent.createChooser(myIntent, "Share Image"));
            }catch(Exception ex)
            {
                
            }
            break;
        
                case R.id.menuBrowse:
            try{
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent, "Select Picture"),1);
            }catch(Exception ex)
            {
                
            }

        break;
        }        
        return true;

    }


仔细观察 `menuShare` 部分。观察 `ACTION.SEND` Intent 的使用。您可以直接将 `fileUri` 传递给 `EXTRA_STREAM` 字段。您可以使用 `putExtra` 方法添加更多信息。

获取绝对路径仅用于在我们的图像视图中显示所选图像。

public String getRealPathFromURI(Uri contentUri) {
          String[] proj = { MediaStore.Images.Media.DATA };
          
          //This method was deprecated in API level 11
          //Cursor cursor = managedQuery(contentUri, proj, null, null, null);
          
          CursorLoader cursorLoader = new CursorLoader(
                    this, 
                    contentUri, proj, null, null, null);        
          Cursor cursor = cursorLoader.loadInBackground();
          
          int column_index = 
            cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
          cursor.moveToFirst();
          return cursor.getString(column_index); 
         }
    

最后,这是输出:

图 4.1:通过 Intent 共享的结果

当您选择一个选项时,主题和描述字段将得到很好的对齐。

图 4.2:选择共享选项后的数据

请注意,此选项显示的是设备上安装的共享选项。例如,我的设备上未安装 Facebook 应用。因此,它不显示 Facebook 选项。如果您安装了 Facebook、LinkedIn,所有这些选项都会出现在共享 Intent 视图中。

 

5. 结论

© . All rights reserved.