Здравствуйте, у меня недавно появилась задача написать небольшую программу в которой будет использоваться facebook api и сегодня я хочу рассказать вам собственно как работать с этим api.
Программа будет выполнять простые действия, залогиниться в фейсбук, вывести список друзей с фотографиями, вывести детальную информацию о определенном человеке тоже с фотографией и по клику по фотографии вывести большую фотку.
Для начала нам нужно скачать само api для работы с фейсбуком, его вы можете скачать или у меня с дропбокса или с официальной страницы фейсбука для разработчиков, лучше конечно у меня скачайте потому что там непонятная фигня творится когда подключаешь версию ниже или выше.
Так же для этого туториала я использовал библиотеку для скачивания картинок, она лежит в архиве с моим SSDK так что если вы скачаете мое то проблем возникнуть не должно. Ну а если для общего развития то скачать её можно вот здесь.
Настройка проекта
Теперь когда вы скачали SDK можно приступать к настройке проекта для работы с фейсбуком. Для начала импортируйте проект facebook api 3.0 в эклипс.
Все примеры импортировать не нужно, если только вы не собираетесь разбирать их код, а только проект facebook.
Далее в вашем проекте кликаем по нему правой кнопкой и выбираем в самом низу Propertis, выбираем вкладку Android и внизу нажимаем кнопку Add и выбираем наше SDK.
Вот теперь мы добавили facebook sdk в наш проект и можем спокойно работать с ихним api.
Инициализация приложения в facebook
Далее нам нужно создать Android приложение в facebook developer tools, для этого переходим на страницу создания приложения и создаем там свое приложение, там по пунктам все, так что надеюсь сами разберетесь (:.
В итоге у вас должно получиться что-то на подобии вот такого:
Для работы приложения нам нужен App ID/API Key которым у нас является вот этот набор цифр 343214545779491, далее в проекте я буду его использовать для инициализации приложения.
Ну а теперь можно приступить к разработке.
Вход в учетную запись и вывод списка друзей
Я объедении эти два пункта для простоты понимания, так как у нас логин и вывод списка находится в одной активности будет проще понять код.
Для начала давайте опишем наш AndroidManifest, в нем нам нужно описать что мы будем использовать интернет и к каким активностям мы будем обращаться.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.facebook_api_sample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="9" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.facebook_api_sample.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.example.facebook_api_sample.DetalsActivity"></activity>
<activity android:name="com.example.facebook_api_sample.FullAvatarActivity"></activity>
</application>
</manifest>
Все эти активности я опишу ниже.
Далее нам в нашем MainActivity нужно определить переменные которые будут использоваться для работы с SDK и обычные переменные для ввода и вывода контента. Так же у нас будет функция логина и функция вывода в листвью списка друзей с фотографиями через кастомный адаптер (создание кастомного адаптера я опишу в следующей статье, этот не сильно хорош...).
И так наш класс умеет:
- Логиниться
- Выводить список друзей с фотографиями
Смотрим как это реализовано:
MainActivity
import adapter.FriendsAdapter;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.AsyncFacebookRunner.RequestListener;
import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.Facebook.DialogListener;
import com.facebook.android.FacebookError;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
public class MainActivity extends Activity {
// собственно ID приложения из facebook dev tools
// измените на свой
private static String APP_ID = "343214545779491";
private static final String FIRST = "name";
private static final String IMAGE = "image";
private static final String LAST = "id";
//массив в котором будем хранить список друзей с фотографиями
private static ArrayList<HashMap<String, Object>> myUsers;
// Инициализируем класс фейсбук
private Facebook facebook;
//запускаем его для работы
private AsyncFacebookRunner mAsyncRunner;
private SharedPreferences mPrefs;
private String FILENAME = "AndroidSSO_data";
private int i = 0;
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView1);
//инициализируем наши объекты
facebook = new Facebook(APP_ID);
mAsyncRunner = new AsyncFacebookRunner(facebook);
mPrefs = getPreferences(MODE_PRIVATE);
//проверяем залогинен пользователь или нет
//если залогинен то сразу выводим список друзей
//если нет то выводим окно логина
String access_token = mPrefs.getString("access_token", null);
long expires = mPrefs.getLong("access_expires", 0);
if (access_token != null) {
facebook.setAccessToken(access_token);
Log.d("FB Sessions", "" + facebook.isSessionValid());
}
if (expires != 0) {
facebook.setAccessExpires(expires);
getProfileInformation();
}
if (expires == 0) {
loginToFacebook();
}
myUsers = new ArrayList<HashMap<String, Object>>();
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
HashMap<String, Object> item = myUsers.get(position);
String key = item.get(LAST).toString();
//передаем id пользователя для вывода полной информации
Intent intent = new Intent(MainActivity.this, DetalsActivity.class);
intent.putExtra(DetalsActivity.JSON, key);
startActivity(intent);
}
});
}
/** Забираем информацию списка друзей при помощи graph anpi */
@SuppressWarnings("deprecation")
public void getProfileInformation() {
Bundle params = new Bundle();
params.putString("fields", "name, picture");
//посылаем запрос на вывод всех друзей с картинками и именами
mAsyncRunner.request("me/friends", params, new RequestListener() {
@Override
public void onComplete(String response, Object state) {
//json который приходит с сервера
String json = response;
try {
JSONObject profile = new JSONObject(json);
JSONArray data = profile.getJSONArray("data");
for (i = 0; i < data.length(); i++) {
// забираем данные из json
final String name = data.getJSONObject(i).getString("name");
final String id = data.getJSONObject(i).getString("id");
JSONObject picture = data.getJSONObject(i).getJSONObject("picture");
JSONObject picdata = picture.getJSONObject("data");
final String url = picdata.getString("url");
runOnUiThread(new Runnable() {
@Override
public void run() {
//закидываем в массив все что получили
HashMap<String, Object> hm;
hm = new HashMap<String, Object>();
hm.put(FIRST, name);
hm.put(LAST, id);
hm.put(IMAGE, url);
myUsers.add(hm);
//вытаскиваем для передачи в адаптер (так лучше не делать, мой косяк)
String[] urls = new String[myUsers.size()];
String[] names = new String[myUsers.size()];
String[] indexcode = new String[myUsers.size()];
for (int i = 0; i < myUsers.size(); i++) {
urls[i] = (String) myUsers.get(i).get(IMAGE);
names[i] = (String) myUsers.get(i).get(FIRST);
indexcode[i] = (String) myUsers.get(i).get(LAST);
}
//передаем в адаптер для распечатки
listView.setAdapter(new FriendsAdapter(MainActivity.this, indexcode, names, urls));
}
});
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFacebookError(FacebookError e, Object state) {
}
@Override
public void onFileNotFoundException(FileNotFoundException e, Object state) {
}
@Override
public void onIOException(IOException e, Object state) {
}
@Override
public void onMalformedURLException(MalformedURLException e, Object state) {
}
});
}
/** Функция логина в фейсбук*/
@SuppressWarnings("deprecation")
public void loginToFacebook() {
if (!facebook.isSessionValid()) {
facebook.authorize(this, new String[] { "email", "publish_stream" },
new DialogListener() {
@Override
public void onCancel() {
//функция отмены действия
}
@Override
public void onComplete(Bundle values) {
// сохраняем данные что бы не вводить по триста раз на день
// при входе заполняем
SharedPreferences.Editor editor = mPrefs.edit();
editor.putString("access_token", facebook.getAccessToken());
editor.putLong("access_expires", facebook.getAccessExpires());
editor.commit();
getProfileInformation();
}
@Override
public void onError(DialogError error) {
// функция ошибки
}
@Override
public void onFacebookError(FacebookError fberror) {
// функция фейсбучной ошибки
}
});
}
}
}
А дальше нам в нашу разметку main.xml нужно добавить ListView для отображения контента и создать еще один файл разметки friendlist.xml который мы будем заполнять из адаптера.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Теперь создадим адаптер который будет скачивать фотки и выводить полученные данные. Выглядеть он будет просто.
FriendsAdapter
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.facebook_api_sample.R;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
public class FriendsAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] id;
private final String[] images;
private final String[] values;
DisplayImageOptions options;
public FriendsAdapter(Context runnable, String[] indexcode, String[] names, String[] urls) {
super(runnable, R.layout.friendlist, names);
context = runnable;
values = names;
images = urls;
id = indexcode;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.friendlist, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.label);
ImageView imageView = (ImageView) rowView.findViewById(R.id.logo);
textView.setText(values[position]);
//
options = new DisplayImageOptions.Builder().cacheInMemory().cacheOnDisc().bitmapConfig(
Bitmap.Config.RGB_565).build();
//по заданому url скачиваем фотографию
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(getContext()));
imageLoader.displayImage(images[position], imageView, options);
return rowView;
}
}
Здесь у нас есть всего два метода, первый это конструктор в котором мы определяем что куда и зачем будем записывать, а второй метод у нас захватывает данные и полученные параметры обрабатывает и передает на активность.
А дальше напишем для него разметку чтобы выводить данные которые он будет скачивать и показывать. Тут у нас будет текствью с картинкой.
friendlist.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="wrap_content"
android:padding="5dp" >
<ImageView
android:id="@+id/logo"
android:layout_width="50px"
android:layout_height="50px"
android:layout_marginLeft="5px"
android:layout_marginRight="20px"
android:layout_marginTop="5px" >
</ImageView>
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30px" >
</TextView>
</LinearLayout>
Теперь когда вы запустите проект вы увидите что-то на подобии этого:
Теперь нам нужно получать полную информацию о пользователе, переходи к следующему разделу — вывод информации о пользователе.
Вывод информации о пользователе
Что собственно тут будет, во второй активности мы будем получать айдишник пользователя и делать запрос к graph api для вывода информации о нем. Код совершенно похож на предыдущий, отличается только отсутствием функции логина и проверкой на залогинен ли человек или нет, так как это мы проверяем на первом этапе в главной активности.
DetalsActivity
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.AsyncFacebookRunner.RequestListener;
import com.facebook.android.Facebook;
import com.facebook.android.FacebookError;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
public class DetalsActivity extends Activity {
// строчичка которая принимает айдишник из главного класса
public static String JSON;
// собственно ID приложения из facebook dev tools
// измените на свой
private static String APP_ID = "343214545779491";
private TextView data;
// Инициализируем класс фейсбук
private final Facebook facebook = new Facebook(APP_ID);
//запускаем его для работы
private AsyncFacebookRunner mAsyncRunner;
protected ImageLoader imageLoader = ImageLoader.getInstance();
ImageView imageView;
String url;
/** @param key */
@SuppressWarnings("deprecation")
public void getAvatar(String key) {
mAsyncRunner.request(key + "/picture?type=large&redirect=false&", new RequestListener() {
@Override
public void onComplete(final String response, Object state) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject profile = new JSONObject(response);
JSONObject data = profile.getJSONObject("data");
String url = data.getString("url");
//по заданому url скачиваем фотографию
imageLoader.init(ImageLoaderConfiguration.createDefault(DetalsActivity.this));
imageLoader.displayImage(url, imageView);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
@Override
public void onFacebookError(FacebookError e, Object state) {
}
@Override
public void onFileNotFoundException(FileNotFoundException e, Object state) {
}
@Override
public void onIOException(IOException e, Object state) {
}
@Override
public void onMalformedURLException(MalformedURLException e, Object state) {
}
});
}
/** @param key
* Получаем информацию о пользователе по его айди*/
@SuppressWarnings("deprecation")
public void getFriendInformation(String key) {
//id + всеп поля которые мы хотим видеть
mAsyncRunner.request(key + "?fields=id,name,gender,locale,birthday,hometown,languages,timezone&",
new RequestListener() {
@Override
public void onComplete(final String response, Object state) {
runOnUiThread(new Runnable() {
@Override
public void run() {
//снова json который возвращает сервер
String json = response;
try {
JSONObject profile = new JSONObject(json);
// getting name of the user
String json_name = profile.getString("name");
String json_male = profile.getString("gender");
String json_locale = profile.getString("locale");
//
data.setText("Name: " + json_name + "\nMale: " + json_male + "\nLocale: "
+ json_locale);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
@Override
public void onFacebookError(FacebookError e, Object state) {
}
@Override
public void onFileNotFoundException(FileNotFoundException e, Object state) {
}
@Override
public void onIOException(IOException e, Object state) {
}
@Override
public void onMalformedURLException(MalformedURLException e, Object state) {
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
setContentView(R.layout.details_activity_layout);
mAsyncRunner = new AsyncFacebookRunner(facebook);
data = (TextView) findViewById(R.id.textView2);
//
Bundle extras = getIntent().getExtras();
final String key = extras.getString(JSON);
//
imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//по клику передаем снова ключ в следующий класс
Intent intent = new Intent(DetalsActivity.this, FullAvatarActivity.class);
intent.putExtra(FullAvatarActivity.JSON, key);
startActivity(intent);
}
});
//ключ для функции получения иформации
getFriendInformation(key);
//ключ для получения аватара
getAvatar(key);
}
}
И так что тут происходит? У нас есть два метода которые делают запрос на получения json с фейсбука, getFriendInformation() — делает запрос на получение инфо о юзере по его айдишнику, а getAvatar() — делает запрос на получение ссылки на аватарку пользователя по тому же айдишнику. Оба метода запускаются одновременно при старте активности.
В onCreate() мы принимаем в переменную JSON данные которые приходят с класса MainActivity и сразу же передаем их в наши методы.
Замечание: Если вы хотите получить как можно больше данных вам нужно искать пользователей с открытыми профилями, если профиль закрыт для внешнего просмотра вы сможете просмотреть только имя с фамилией, локацию и пол.
Разметка нашего класса будет выглядеть таким образом:
detals_activity_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="24dp"
android:layout_toRightOf="@+id/imageView1"
android:text="no data"
android:textSize="20sp" />
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@android:drawable/ic_delete" />
</RelativeLayout>
А на аппарате выглядеть оно будет вот так:
Ну а теперь нам осталось создать последнюю активность в которой мы будем выводить большую фотографию по клику на фотку в DetalsActivity.
Просмотр большого автара
Тут все идентично предыдущему пункту, все точь в точь, будем делать запрос ик в котором будем указывать айдишнк пользователя и после чего будем получать ссылку на фотографию пользователя. Вся работа с фейсбуком в принципе сводится к постоянной работе с json так что если вы не умеете работать с данной технологией сперва лучше подтяните её, а потом лезте уже в это болото.
FullAvatarActivity
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.ImageView;
import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.AsyncFacebookRunner.RequestListener;
import com.facebook.android.Facebook;
import com.facebook.android.FacebookError;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
public class FullAvatarActivity extends FragmentActivity {
public static String JSON;
private static String APP_ID = "343214545779491"; // Replace with your App ID
private final Facebook facebook = new Facebook(APP_ID);
private AsyncFacebookRunner mAsyncRunner;
protected ImageLoader imageLoader = ImageLoader.getInstance();
ImageView imageView;
/** @param key */
@SuppressWarnings("deprecation")
public void getBigImage(String key) {
mAsyncRunner.request(key + "/picture?width=500&height=500&redirect=false&", new RequestListener() {
@Override
public void onComplete(final String response, Object state) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject profile = new JSONObject(response);
JSONObject data = profile.getJSONObject("data");
String url = data.getString("url");
Log.v("", "" + url);
imageLoader.init(ImageLoaderConfiguration.createDefault(FullAvatarActivity.this));
imageLoader.displayImage(url, imageView);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
@Override
public void onFacebookError(FacebookError e, Object state) {
}
@Override
public void onFileNotFoundException(FileNotFoundException e, Object state) {
}
@Override
public void onIOException(IOException e, Object state) {
}
@Override
public void onMalformedURLException(MalformedURLException e, Object state) {
}
});
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.big_image);
mAsyncRunner = new AsyncFacebookRunner(facebook);
imageView = (ImageView) findViewById(R.id.userimage);
Bundle extras = getIntent().getExtras();
String key = extras.getString(JSON);
getBigImage(key);
}
}
И разметка к классу которая состоит только из одного элемента — imageView.
big_image.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#000" >
<ImageView
android:id="@+id/userimage"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
После запуска и переходов по активностям у вас должно получиться что-то на подобии вот такого:
Ссылки
- Getting Started with the Facebook SDK for Android
- Введение в API-интерфейсы Facebook
- Facebook connect tutorial
--
Вот так вот можно работать с фейсбучным апи, помимо обычного конекта там еще очень много функций, но я решил рассказать именно про это так как столкнулся с таким заданием. Всем спасибо за внимание, всем хорошего дня.
Скачать с GitHub && Скачать с Dropbox
не работает пример, после авторизации просто белый экран.
ОтветитьУдалитьПерегрузите программу возможно данные загрузились но не обновились в активити.
УдалитьЭтот комментарий был удален автором.
УдалитьНичего не меняется... И вообще там очень много всего что Depreceted, может из за этого?
УдалитьНет не из за этого, возможно забыли интернет включить? Или еще какие факторы, я прежде чем исходники заливать проверял.
УдалитьБуду обязательно пробовать ещё!
УдалитьНет все-равно не работает. Здесь даже тему уже завели http://www.cyberforum.ru/android-dev/thread855383.html
ОтветитьУдалитьКстати, всё получилось - причиной было, неимение друзей на фейсбуке. И ещё проект лежащий на ГитХабе и ДропБоксе отличаются по коду. Можно это заметить в классе MainActivity в методе getProfileInformation();
ОтветитьУдалитькак можно сделать LogOut?
ОтветитьУдалитьhttp://stackoverflow.com/questions/8323449/how-to-logout-using-facebook-api-in-android
УдалитьСпасибо, подробно описали. Я что-то похожее писал http://plutov.by/post/social_photo_import
ОтветитьУдалить