Added:
/branches/2009q4rewrite/android
/branches/2009q4rewrite/android/build.properties
/branches/2009q4rewrite/android/build.xml
/branches/2009q4rewrite/android/demos
/branches/2009q4rewrite/android/demos/friendlist
/branches/2009q4rewrite/android/demos/friendlist/AndroidManifest.xml
/branches/2009q4rewrite/android/demos/friendlist/README
/branches/2009q4rewrite/android/demos/friendlist/build.properties
/branches/2009q4rewrite/android/demos/friendlist/build.xml
/branches/2009q4rewrite/android/demos/friendlist/default.properties
/branches/2009q4rewrite/android/demos/friendlist/libs
/branches/2009q4rewrite/android/demos/friendlist/libs/commons-codec-1.3.jar
/branches/2009q4rewrite/android/demos/friendlist/libs/json_simple-1.1.jar
/branches/2009q4rewrite/android/demos/friendlist/libs/oauth-20090825.jar
/branches/2009q4rewrite/android/demos/friendlist/libs/opensocial-android.jar
/branches/2009q4rewrite/android/demos/friendlist/libs/opensocial.jar
/branches/2009q4rewrite/android/demos/friendlist/src
/branches/2009q4rewrite/android/demos/friendlist/src/org
/branches/2009q4rewrite/android/demos/friendlist/src/org/opensocial
/branches/2009q4rewrite/android/demos/friendlist/src/org/opensocial/android
/branches/2009q4rewrite/android/demos/friendlist/src/org/opensocial/android/demos
/branches/2009q4rewrite/android/demos/friendlist/src/org/opensocial/android/demos/friendlist
/branches/2009q4rewrite/android/demos/friendlist/src/org/opensocial/android/demos/friendlist/FriendListActivity.java
/branches/2009q4rewrite/android/demos/friendlist/src/org/opensocial/android/demos/friendlist/FriendListView.java
/branches/2009q4rewrite/android/lib
/branches/2009q4rewrite/android/lib/commons-codec-1.3.jar
/branches/2009q4rewrite/android/lib/json_simple-1.1.jar
/branches/2009q4rewrite/android/lib/oauth-20090825.jar
/branches/2009q4rewrite/android/lib/opensocial.jar
/branches/2009q4rewrite/android/src
/branches/2009q4rewrite/android/src/org
/branches/2009q4rewrite/android/src/org/opensocial
/branches/2009q4rewrite/android/src/org/opensocial/android
/branches/2009q4rewrite/android/src/org/opensocial/android/OpenSocialActivity.java
/branches/2009q4rewrite/android/src/org/opensocial/android/OpenSocialChooserActivity.java
Modified:
/branches/2009q4rewrite/java/src/org/opensocial/auth/OAuthScheme.java
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/build.properties Sun Dec 27 23:15:12
2009
@@ -0,0 +1,5 @@
+# Change to point to location of Android SDK.
+# For example: sdk-location=/home/${USER}/android-sdk
+sdk-location=
+# Set the Android OS version to target, e.g. 1.5, 1.6, 2.0, ...
+release-target=1.5
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/build.xml Sun Dec 27 23:15:12 2009
@@ -0,0 +1,67 @@
+<project name="OpenSocial Client Library for Android" default="compile"
basedir=".">
+
+ <property name="app.name" value="opensocial-android"/>
+
+ <!-- Paths for source code and compiled files -->
+ <property name="src.home" value="${basedir}/src"/>
+ <property name="build.home" value="${basedir}/bin"/>
+
+ <!-- Path for dependent libraries -->
+ <property name="lib.home" value="${basedir}/lib"/>
+
+ <!-- Path for packaged distribution files -->
+ <property name="dist.home" value="${basedir}/dist"/>
+
+ <!-- The build.properties file can be created by you and is never touched
+ by the 'android' tool. This is the place to change some of the
default property values
+ used by the Ant rules.
+ Here are some properties you may want to change:
+
+ application-package
+ the name of your application package as defined in the
manifest. Used by the
+ 'uninstall' rule.
+ source-folder
+ the name of the source folder. Default is 'src'.
+ out-folder
+ the name of the output folder. Default is 'bin'.
+
+ Properties related to the SDK location or the project target should
be updated
+ using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
application and
+ should be checked in in Version Control Systems.
+
+ -->
+ <property file="build.properties"/>
+
+ <path id="compile-src.classpath">
+ <fileset dir="${lib.home}">
+ <include name="*.jar"/>
+ </fileset>
+ <fileset dir="${sdk-location}/platforms/android-${release-target}">
+ <include name="android.jar"/>
+ </fileset>
+ </path>
+
+ <target name="compile" description="Compile Java sources">
+ <mkdir dir="${build.home}"/>
+ <javac destdir="${build.home}" debug="true"
debuglevel="lines,vars,source">
+ <classpath refid="compile-src.classpath"/>
+ <src path="${src.home}"/>
+ </javac>
+ </target>
+
+ <target name="dist" depends="compile" description="Create packaged
distribution files">
+ <mkdir dir="${dist.home}"/>
+ <jar jarfile="${dist.home}/${app.name}.jar">
+ <fileset dir="${src.home}" />
+ <fileset dir="${build.home}"/>
+ </jar>
+ </target>
+
+ <target name="clean">
+ <delete dir="${build.home}"/>
+ <delete dir="${dist.home}"/>
+ </target>
+
+</project>
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/demos/friendlist/AndroidManifest.xml
Sun Dec 27 23:15:12 2009
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.
+ */
+-->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.opensocial.android.demos.friendlist"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:label="OpenSocial Friend List">
+ <activity
+ android:name=".FriendListActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER"
/>
+ </intent-filter>
+ <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-opensocial-demo-app"/> <!-- MAKE
SURE TO REPLACE THIS -->
+ </intent-filter>
+ </activity>
+ <activity
android:name="org.opensocial.android.OpenSocialChooserActivity"></activity>
+ </application>
+ <uses-permission android:name="android.permission.INTERNET" />
+</manifest>
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/demos/friendlist/README Sun Dec 27
23:15:12 2009
@@ -0,0 +1,50 @@
+OpenSocial Android client library -- friendlist demo
+
+friendlist is a simple sample application designed to introduce the
OpenSocial
+client library for Android. It includes a single Activity which first
prompts
+the user to choose one from a list of OpenSocial providers, then uses
three-
+legged OAuth to authenticate the user and fetch all friends from the
selected
+provider. The list of friends is rendered directly in the Android
application
+using the included View. The user can tap a name to see all information
+available for that friend.
+
+This is an Android application, and you will need to download the Android
SDK
+in order to build and run it:
+
+1. If you haven't already, download the latest Android SDK from
+ http://developer.android.com/sdk/index.html and unzip it.
+2. Open build.properties and update the sdk-location property to point to
the
+ location of your downloaded SDK.
+3. OPTIONAL: If necessary, open default.properties and update the SDK
target
+ from the default level.
+4. To run the application in the Android emulator, first launch the
emulator
+ (see http://developer.android.com/guide/developing/tools/emulator.html
if
+ you're new to Android), then open a new command line window, navigate to
+ the friendlist directory, and execute 'ant install' -- you should see
+ "OpenSocial Friend List" in the set of applications. From here, you can
+ invoke 'ant reinstall' to reinstall the application or 'ant uninstall'
to
+ remove it from the application set.
+
+
+- File contents:
+
+. AndroidManifest.xml:
+ Standard AndroidManifest which declares FriendListActivity and
+ OpenSocialChooserActivity and requests INTERNET permission.
+
+. build.properties:
+ Properties file for ant.
+
+. build.xml:
+ Build file for ant.
+
+. default.properties:
+ Specifies Android target level.
+
+. src/org/opensocial/android/demos/friendlist/FriendListActivity.java:
+ Subclass of OpenSocialActivity; displays a list of OpenSocial providers
to
+ select from, then fetches the user's friends once the user is
authenticated
+ to the selected provider.
+
+. src/org/opensocial/android/demos/friendlist/FriendListView.java:
+ Subclass of View; displays the user's friends.
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/demos/friendlist/build.properties Sun
Dec 27 23:15:12 2009
@@ -0,0 +1,4 @@
+# Change to point to location of Android SDK.
+# For example: sdk-location=/home/${USER}/android-sdk
+sdk-location=
+application-package=org.opensocial.android.demos.friendlist
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/demos/friendlist/build.xml Sun Dec 27
23:15:12 2009
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="AndroidApplication" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android'
tool.
+ It contain the path to the SDK. It should *NOT* be checked in in
Version
+ Control Systems. -->
+ <property file="local.properties"/>
+
+ <!-- The build.properties file can be created by you and is never
touched
+ by the 'android' tool. This is the place to change some of the
default property values
+ used by the Ant rules.
+ Here are some properties you may want to change:
+
+ application-package
+ the name of your application package as defined in the
manifest. Used by the
+ 'uninstall' rule.
+ source-folder
+ the name of the source folder. Default is 'src'.
+ out-folder
+ the name of the output folder. Default is 'bin'.
+
+ Properties related to the SDK location or the project target
should be updated
+ using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
application and
+ should be checked in in Version Control Systems.
+
+ -->
+ <property file="build.properties"/>
+
+ <!-- The default.properties file is created and updated by
the 'android' tool, as well
+ as ADT.
+ This file is an integral part of the build system for your
application and
+ should be checked in in Version Control Systems. -->
+ <property file="default.properties"/>
+
+ <!-- Custom Android task to deal with the project target, and import
the proper rules.
+ This requires ant 1.6.0 or above. -->
+ <path id="android.antlibs">
+ <pathelement path="${sdk-location}/tools/lib/anttasks.jar" />
+ <pathelement path="${sdk-location}/tools/lib/sdklib.jar" />
+ <pathelement path="${sdk-location}/tools/lib/androidprefs.jar" />
+ <pathelement path="${sdk-location}/tools/lib/apkbuilder.jar" />
+ <pathelement path="${sdk-location}/tools/lib/jarutils.jar" />
+ </path>
+
+ <taskdef name="setup"
+ classname="com.android.ant.SetupTask"
+ classpathref="android.antlibs"/>
+
+ <!-- Execute the Android Setup task that will setup some properties
specific to the target,
+ and import the rules files.
+ To customize the rules, copy/paste them below the task, and
disable import by setting
+ the import attribute to false:
+ <setup import="false" />
+
+ This will ensure that the properties are setup correctly but that
your customized
+ targets are used.
+ -->
+ <setup />
+</project>
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/demos/friendlist/default.properties Sun
Dec 27 23:15:12 2009
@@ -0,0 +1,2 @@
+# Android SDK Target level.
+target=android-3
=======================================
--- /dev/null
+++
/branches/2009q4rewrite/android/demos/friendlist/libs/commons-codec-1.3.jar
Sun Dec 27 23:15:12 2009
Binary file, no diff available.
=======================================
--- /dev/null
+++
/branches/2009q4rewrite/android/demos/friendlist/libs/json_simple-1.1.jar
Sun Dec 27 23:15:12 2009
Binary file, no diff available.
=======================================
--- /dev/null
+++
/branches/2009q4rewrite/android/demos/friendlist/libs/oauth-20090825.jar
Sun Dec 27 23:15:12 2009
Binary file, no diff available.
=======================================
--- /dev/null
+++
/branches/2009q4rewrite/android/demos/friendlist/libs/opensocial-android.jar
Sun Dec 27 23:15:12 2009
Binary file, no diff available.
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/demos/friendlist/libs/opensocial.jar
Sun Dec 27 23:15:12 2009
Binary file, no diff available.
=======================================
--- /dev/null
+++
/branches/2009q4rewrite/android/demos/friendlist/src/org/opensocial/android/demos/friendlist/FriendListActivity.java
Sun Dec 27 23:15:12 2009
@@ -0,0 +1,125 @@
+/* Copyright (c) 2009 Google Inc.
+ *
+ * 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.
+ */
+
+package org.opensocial.android.demos.friendlist;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.opensocial.Client;
+import org.opensocial.Request;
+import org.opensocial.RequestException;
+import org.opensocial.android.OpenSocialActivity;
+import org.opensocial.models.Person;
+import org.opensocial.providers.GoogleProvider;
+import org.opensocial.services.PeopleService;
+
+import java.io.IOException;
+import java.util.List;
+
+public class FriendListActivity extends OpenSocialActivity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ setScheme("x-opensocial-demo-app");
+
+ addProvider(new GoogleProvider(), new String[] {"anonymous",
+ "anonymous"});
+
+ super.onCreate(savedInstanceState);
+
+ setupClient();
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+
+ if (hasFocus) {
+ setupClient();
+ }
+ }
+
+ private void setupClient() {
+ Client client = getClient();
+
+ if (client == null) {
+ showChooser();
+ } else {
+ showContacts(client);
+ }
+ }
+
+ private void showContacts(Client client) {
+ List<Person> friends = null;
+ try {
+ Request request = PeopleService.retrieve("@me", "@all");
+ friends = client.send(request).getEntries();
+ } catch (RequestException e) {
+ Log.i("DisplayFriendActivity", "Couldn't fetch friends from the " +
+ "container: " + e.getMessage());
+ } catch (IOException e) {
+ Log.i("DisplayFriendActivity", "Couldn't fetch friends from the " +
+ "container: " + e.getMessage());
+ }
+
+ LinearLayout linearLayout = new LinearLayout(this);
+ linearLayout.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.FILL_PARENT,
+ LinearLayout.LayoutParams.FILL_PARENT));
+ linearLayout.setOrientation(LinearLayout.VERTICAL);
+
+ if (friends != null && friends.size() > 0) {
+ FriendListView contactsView = new FriendListView(this);
+ contactsView.setFriends(friends);
+ contactsView.setVerticalScrollBarEnabled(true);
+ contactsView.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT, 300));
+ linearLayout.addView(contactsView);
+ } else {
+ TextView textView = new TextView(this);
+ textView.setText("No contacts found.");
+ linearLayout.addView(textView);
+ }
+
+ final FriendListActivity activity = this;
+
+ Button clearAuthButton = new Button(this);
+ clearAuthButton.setText("Clear Auth");
+ clearAuthButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View view) {
+ clearSavedAuthentication();
+ }
+ });
+
+ Button fetchFriendsButton = new Button(this);
+ fetchFriendsButton.setText("Fetch Friends");
+ fetchFriendsButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View view) {
+ activity.setupClient();
+ }
+ });
+
+ linearLayout.addView(fetchFriendsButton);
+ linearLayout.addView(clearAuthButton);
+
+ setContentView(linearLayout);
+ }
+}
=======================================
--- /dev/null
+++
/branches/2009q4rewrite/android/demos/friendlist/src/org/opensocial/android/demos/friendlist/FriendListView.java
Sun Dec 27 23:15:12 2009
@@ -0,0 +1,103 @@
+/* Copyright (c) 2009 Google Inc.
+ *
+ * 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.
+ */
+
+package org.opensocial.android.demos.friendlist;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import org.opensocial.models.Person;
+
+import java.util.List;
+
+/**
+ * Demo class. Displays a list of contacts.
+ *
+ * @author Cassandra Doll
+ */
+public class FriendListView extends ListView {
+ public FriendListView(Context context) {
+ super(context);
+
+ this.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ public void onItemClick(AdapterView<?> parent, View view, int
position, long id) {
+ ((ContactView) view).toggle();
+ }
+ });
+ }
+
+ public void setFriends(final List<Person> contacts) {
+ this.setAdapter(new BaseAdapter() {
+
+ public int getCount() {
+ return contacts.size();
+ }
+
+ public Object getItem(int i) {
+ return contacts.get(i);
+ }
+
+ public long getItemId(int i) {
+ return i;
+ }
+
+ public View getView(int position, View convertView, ViewGroup
parent) {
+ Person c = contacts.get(position);
+ return new ContactView(FriendListView.this.getContext(), c);
+ }
+ });
+ }
+
+ public static class ContactView extends LinearLayout {
+ private boolean expanded = false;
+ private TextView textView;
+ private String compactText;
+ private String expandedText;
+
+ public ContactView(Context context, Person c) {
+ super(context);
+
+ compactText = c.getDisplayName();
+ expandedText = c.toString();
+
+ textView = new TextView(context);
+ textView.setText(compactText);
+ textView.setTextSize(18);
+
+ this.addView(textView);
+ }
+
+ public void toggle() {
+ setExpanded(!this.expanded);
+ }
+
+ private void setExpanded(boolean b) {
+ expanded = b;
+
+ if (expanded) {
+ textView.setText(expandedText);
+ } else {
+ textView.setText(compactText);
+ }
+ }
+
+ }
+}
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/lib/commons-codec-1.3.jar Sun Dec 27
23:15:12 2009
Binary file, no diff available.
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/lib/json_simple-1.1.jar Sun Dec 27
23:15:12 2009
Binary file, no diff available.
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/lib/oauth-20090825.jar Sun Dec 27
23:15:12 2009
Binary file, no diff available.
=======================================
--- /dev/null
+++ /branches/2009q4rewrite/android/lib/opensocial.jar Sun Dec 27 23:15:12
2009
Binary file, no diff available.
=======================================
--- /dev/null
+++
/branches/2009q4rewrite/android/src/org/opensocial/android/OpenSocialActivity.java
Sun Dec 27 23:15:12 2009
@@ -0,0 +1,202 @@
+/* Copyright (c) 2009 Google Inc.
+ *
+ * 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.
+ */
+
+package org.opensocial.android;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthException;
+
+import org.opensocial.Client;
+import org.opensocial.auth.OAuth3LeggedScheme;
+import org.opensocial.providers.Provider;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+
+public class OpenSocialActivity extends Activity {
+
+ public static final String CLASS = "class";
+ public static final String SCHEME = "scheme";
+ public static final String PROVIDERS = "providers";
+ public static final String CREDENTIALS = "credentials";
+ public static final String ACCESS_TOKEN = "accesstoken";
+ public static final String REQUEST_TOKEN = "requesttoken";
+ public static final String SELECTED_PROVIDER = "selectedprovider";
+ public static final String ACCESS_TOKEN_SECRET = "accesstokensecret";
+ public static final String REQUEST_TOKEN_SECRET = "requesttokensecret";
+
+ private HashMap<String, Class<? extends Provider>> providerClasses =
+ new HashMap<String, Class<? extends Provider>>();
+ private HashMap<String, String[]> providerCredentials =
+ new HashMap<String, String[]>();
+ private String scheme = "";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (getIntent().getData() != null) {
+ Provider provider = loadSelectedProvider();
+ OAuth3LeggedScheme.Token requestToken = loadRequestToken();
+
+ if (provider != null && requestToken != null) {
+ try {
+ String[] credentials =
providerCredentials.get(provider.getName());
+ OAuth3LeggedScheme authScheme = new OAuth3LeggedScheme(provider,
+ credentials[0], credentials[1]);
+ authScheme.setRequestToken(requestToken);
+ authScheme.requestAccessToken(requestToken.token);
+ persistAccessToken(authScheme.getAccessToken());
+ } catch (OAuthException e) {
+ throw new RuntimeException("Error occured fetching access
token", e);
+ } catch (URISyntaxException e) {
+ throw new RuntimeException("Error occured fetching access
token", e);
+ } catch (IOException e) {
+ throw new RuntimeException("Error occured fetching access
token", e);
+ }
+ }
+ }
+ }
+
+ protected void setScheme(String scheme) {
+ this.scheme = scheme;
+ }
+
+ protected void addProvider(Provider provider, String[] credentials) {
+ if (provider != null && credentials != null && credentials.length ==
2) {
+ providerClasses.put(provider.getName(), provider.getClass());
+ providerCredentials.put(provider.getName(), credentials);
+ }
+ }
+
+ protected Client getClient() {
+ OAuth3LeggedScheme.Token requestToken = loadRequestToken();
+ OAuth3LeggedScheme.Token accessToken = loadAccessToken();
+ Provider provider = loadSelectedProvider();
+
+ if (requestToken != null && accessToken != null && provider != null) {
+ String[] credentials = providerCredentials.get(provider.getName());
+ OAuth3LeggedScheme authScheme = new OAuth3LeggedScheme(provider,
+ credentials[0], credentials[1]);
+ authScheme.setRequestToken(requestToken);
+ authScheme.setAccessToken(accessToken);
+
+ return new Client(provider, authScheme);
+ }
+
+ return null;
+ }
+
+ protected void showChooser() {
+ Intent chooser = new Intent(this, OpenSocialChooserActivity.class);
+
+ String[] providers = providerClasses.keySet().toArray(new String[] {});
+ chooser.putExtra(PROVIDERS, providers);
+ chooser.putExtra(SCHEME, scheme);
+
+ for (String name : providers) {
+ chooser.putExtra(name + CREDENTIALS, providerCredentials.get(name));
+ chooser.putExtra(name + CLASS, providerClasses.get(name));
+ }
+
+ startActivity(chooser);
+ }
+
+ protected void clearSavedAuthentication() {
+ SharedPreferences.Editor editor = getSharedPreferences("default",
+ MODE_PRIVATE).edit();
+
+ editor.remove(ACCESS_TOKEN_SECRET);
+ editor.remove(SELECTED_PROVIDER);
+ editor.remove(ACCESS_TOKEN);
+ editor.commit();
+ }
+
+ private Provider loadSelectedProvider() {
+ SharedPreferences preferences = getSharedPreferences("default",
+ MODE_PRIVATE);
+
+ String name = preferences.getString(SELECTED_PROVIDER, null);
+
+ try {
+ Class<? extends Provider> providerClass = providerClasses.get(name);
+
+ return providerClass.newInstance();
+ } catch (NullPointerException e) {
+ return null;
+ } catch (InstantiationException e) {
+ return null;
+ } catch (IllegalAccessException e) {
+ return null;
+ }
+ }
+
+ private OAuth3LeggedScheme.Token loadRequestToken() {
+ SharedPreferences preferences = getSharedPreferences("default",
+ MODE_PRIVATE);
+
+ String requestTokenSecret = preferences.getString(REQUEST_TOKEN_SECRET,
+ null);
+ String requestToken = preferences.getString(REQUEST_TOKEN, null);
+ Uri data = getIntent().getData();
+
+ if (requestToken != null) {
+ return new OAuth3LeggedScheme.Token(requestToken,
requestTokenSecret);
+ }
+
+ if (data != null) {
+ int tokenIndex = data.toString().indexOf("oauth_token");
+
+ if (tokenIndex != -1) {
+ String token = data.toString().substring(tokenIndex + 12);
+
+ return new
OAuth3LeggedScheme.Token(OAuth.decodePercent(token), "");
+ }
+ }
+
+ return null;
+ }
+
+ private OAuth3LeggedScheme.Token loadAccessToken() {
+ SharedPreferences preferences = getSharedPreferences("default",
+ MODE_PRIVATE);
+
+ String accessTokenSecret = preferences.getString(ACCESS_TOKEN_SECRET,
+ null);
+ String accessToken = preferences.getString(ACCESS_TOKEN, null);
+
+ if (accessToken == null) {
+ return null;
+ }
+
+ return new OAuth3LeggedScheme.Token(accessToken, accessTokenSecret);
+ }
+
+ private void persistAccessToken(OAuth3LeggedScheme.Token token) {
+ SharedPreferences.Editor editor = getSharedPreferences("default",
+ MODE_PRIVATE).edit();
+
+ editor.putString(ACCESS_TOKEN_SECRET, token.secret);
+ editor.putString(ACCESS_TOKEN, token.token);
+ editor.commit();
+ }
+}
=======================================
--- /dev/null
+++
/branches/2009q4rewrite/android/src/org/opensocial/android/OpenSocialChooserActivity.java
Sun Dec 27 23:15:12 2009
@@ -0,0 +1,125 @@
+/* Copyright (c) 2009 Google Inc.
+ *
+ * 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.
+ */
+
+package org.opensocial.android;
+
+import android.app.AlertDialog;
+import android.app.ListActivity;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import net.oauth.OAuthException;
+
+import org.opensocial.auth.OAuth3LeggedScheme;
+import org.opensocial.providers.Provider;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+public class OpenSocialChooserActivity extends ListActivity {
+
+ private String scheme;
+ private String[] providers;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ scheme = getIntent().getStringExtra(OpenSocialActivity.SCHEME);
+ providers =
getIntent().getStringArrayExtra(OpenSocialActivity.PROVIDERS);
+
+ setListAdapter(new ArrayAdapter<String>(this, android.R.layout.
+ simple_list_item_single_choice, providers));
+ }
+
+ @Override
+ protected void onListItemClick(ListView listView, View view, int
position,
+ long id) {
+ final String providerName = providers[position];
+ final OAuth3LeggedScheme authScheme = getAuth(providerName);
+
+ if (authScheme != null) {
+ final AlertDialog alert = new AlertDialog.Builder(this).create();
+ alert.setMessage("To get started, you will need to login to " +
providerName);
+ alert.setButton("Login", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ alert.dismiss();
+
+ String url = null;
+ try {
+ url = authScheme.getAuthorizationUrl(scheme + "://");
+ persistRequestToken(authScheme.getRequestToken(),
providerName);
+ } catch (IOException e) {
+ throw new RuntimeException("Error occured fetching request
token: " + e.getMessage(), e);
+ } catch (URISyntaxException e) {
+ throw new RuntimeException("Error occured fetching request
token", e);
+ } catch (OAuthException e) {
+ throw new RuntimeException("Error occured fetching request
token", e);
+ }
+
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setData(Uri.parse(url));
+ startActivity(i);
+
+ finish();
+ }
+ });
+ alert.show();
+ }
+ }
+
+ private void persistRequestToken(OAuth3LeggedScheme.Token requestToken,
+ String providerName) {
+ SharedPreferences.Editor editor =
+ getSharedPreferences("default", MODE_PRIVATE).edit();
+
+ if (requestToken != null) {
+ editor.putString(OpenSocialActivity.SELECTED_PROVIDER, providerName);
+ editor.putString(OpenSocialActivity.REQUEST_TOKEN,
requestToken.token);
+ editor.putString(OpenSocialActivity.REQUEST_TOKEN_SECRET,
+ requestToken.secret);
+ }
+
+ editor.commit();
+ }
+
+ private OAuth3LeggedScheme getAuth(String name) {
+ Class<? extends Provider> providerClass = (Class<? extends Provider>)
+ getIntent().getSerializableExtra(name + OpenSocialActivity.CLASS);
+ String[] credentials = getIntent().getStringArrayExtra(name +
+ OpenSocialActivity.CREDENTIALS);
+
+ if (providerClass == null || credentials == null ||
+ credentials.length < 2) {
+ return null;
+ }
+
+ try {
+ Provider provider = providerClass.newInstance();
+
+ return new OAuth3LeggedScheme(provider, credentials[0],
credentials[1]);
+ } catch (InstantiationException e) {
+ return null;
+ } catch (IllegalAccessException e) {
+ return null;
+ }
+ }
+}
=======================================
--- /branches/2009q4rewrite/java/src/org/opensocial/auth/OAuthScheme.java
Tue Dec 1 01:39:52 2009
+++ /branches/2009q4rewrite/java/src/org/opensocial/auth/OAuthScheme.java
Sun Dec 27 23:15:12 2009
@@ -15,7 +15,7 @@
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
-public abstract class OAuthScheme {
+abstract class OAuthScheme {
protected String consumerKey;
protected String consumerSecret;