Поиск по этому блогу

среда, 21 января 2015 г.

Авторизация в Facebook через FB SDK 3.0 Android

Продолжаю писать про интеграцию с социальными сетями, теперь я вам расскажу про интеграцию facebook в ваше приложение. У фейсбука апи намного удобней и проще. и есть куча библиотек обеспечивающих полный функционал в пару строк кода, но я же говнокодер, я не люблю изящные решения, я иду в лоб (: По этому в этом посте я расскажу про и интеграцию классического фейсбук сдк в ваше приложение.

Я раньше писал уже про работу с FB, но многое изменилось с того времени (март 2013 года). как ни как почти два года прошло. У фейсбука появилось куча фишек которых в старом апи нет, оно рабочее и в принципе если лень разбираться с новым, хотя он проще и удобней, можно использовать старый, но тогда вы потеряете кучу возможностей по работе с новым апи. 

И так начнем. В создании приложения почти ничего не изменилось, но я повторюсь так как это долгая процедура, хотя там в принципе все упростили.

Заходим вот сюда developers.facebook.com/apps/ и жмем кнопку Add new app. 



У вас должно появиться следующее окно с выбором категории



Дальше выбираем категорию и вписываем название приложения



Теперь выбираем категорию для чего приложение предназначено, будь то музыка, фильмы, игры, бизнес и т.д.



Дальше после того как фейсбук сказал мне что называть свои приложения fb, face… book… и т.д. нельзя, мне пришлось как то извернуться и переименовать приложение по другому, но в общем… 

После всех этих операций вас перекидывает на экран Quick Start, скролим до самого низа до пункта Tell us about your Android project, в котором нужно внести свой package name и активити в которой будет происходить вся ахинея. Это очень важно так как если вы введете не верную активити после нажатия на кнопку ничего просто не будет происходить, я уже это попробовал и не знаю баг это или фича…



После чего дергаем скролом до самого верха и жмем кнопку Skip quick start, так как в этом месте мы все порешали уже. И нас перебрасывает на страницу с App ID который нам собственно и нужен



Нам он нужен по этому скопируйте его куда-то ну или не закрывайте эту страницу.

Дальше нам надо перейти на вкладку Settings в которой у нас нужно сгенерировать Key Hash. Есть два способа получения этого ключа. 

Первый способ и самый удобный — это написание кода в onCreate который в лог выведет вам ваш ключ, этот код выглядит вот так:

try { 
                PackageInfo info =     getPackageManager().getPackageInfo("PROJECTNAME",     PackageManager.GET_SIGNATURES);
                for (Signature signature : info.signatures) {
                    MessageDigest md = MessageDigest.getInstance("SHA");
                    md.update(signature.toByteArray());
                    String sign=Base64.encodeToString(md.digest(), Base64.DEFAULT);
                    Log.e("MY KEY HASH:", sign);
                }
    } catch (NameNotFoundException e) {
        Log.d("nope","nope");
    } catch (NoSuchAlgorithmException e) {
    }


Вставляете его в onCreate в вашей активити и запускаете программу. И есть второй способ, он немного трудней, тут надо генерировать через командную строку.

Открываем командную строку и пишем следующее
keytool -exportcert -alias androiddebugkey -keystore "C:\Users\UserName.android\debug.keystore" | openssl sha1 -binary | openssl base64

Где C:\Users\UserName.android\debug.keystore — адрес к вашему keystore файлу, он обычно лежит как раз по этому адресу который указан выше.

Теперь вам осталось вписать данный ключ в поле Key Hash на странице Settings и нажать кнопку Save.

Подготовления окончены, это наверное самая сложная часть подключения facebook sdk, теперь осталось самое легкое на мой взгляд. Хотя стоп, еще не все.

Нам нужно добавить библиотеку для работы с facebook в проект. Если вы используете Android studio то для вас все будет немного проще. 

Открываем в нашем созданном проекте файл build.gradle и пишем следующие строки
repositories { mavenCentral() }

dependencies {
    ...
    compile 'com.facebook.android:facebook-android-sdk:3.21.1'
}

Как я писал в одной из последних статей, мы тут будем подключать Maven репозиторий что бы не скачивать архив с сдк и не подключать его как отдельный project lib. 

Если же вы используете Eclipse то вам нужно скачать папку facebook c данного git репозитория и подключить его как библиотеку проект к своему проекту в Eclipse.

Теперь все уже точно. Теперь кодинг стопудово начнется. 

Начнем по старинке с разметки, нам нужно вписать нашу кнопку на лэяут и текствью ниже для вывода имени после авторизации.

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:facebook="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <com.facebook.widget.LoginButton
        android:id="@+id/fb_login_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        facebook:confirm_logout="false"
        facebook:fetch_user_info="true"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/textView"
        android:layout_below="@+id/fb_login_button"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

Обратите внимание на вот такое 
xmlns:facebook="http://schemas.android.com/apk/res-auto"

Без этой строчки кнопка будет подсвечиваться вся красным так как леяут не определен как рабочая область для обработки команд фб сдк. По этому не забываем об этой строке.

Дальше нам нужно вписать наш App ID который мы получили при регистрации приложения в string файл.

string.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">FacebookSDKSample</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>

    <string name="fb_api_key">1575310249347338</string>

</resources>

Заметте — это обязательно что бы ключ был прописан в string файле, иначе сдк просто не будет понимать что это ключ если вы его впишите просто так в манифесте.

Теперь нам нужно в манифестве прописать вызов LoginActivity который есть стандартным для сдк, нам никакой LoginActivity создавать не надо… И не забыть прописать доступ в интернет и проверку на наличие интернета.

Вот что нам надо добавить в манифест для полноценной работы с сдк:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />


<activity android:name="com.facebook.LoginActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:label="@string/app_name" />
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/fb_api_key"/>


А вот полностью весь манифест что бы вы понимали где и что надо вставлять.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="dajver.facebooksdksample" >

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <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="dajver.facebooksdksample.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.facebook.LoginActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:label="@string/app_name" />
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/fb_api_key"/>
    </application>

</manifest>


Ну а теперь код. В MainActivity мы инициализируем все методы для работы с сдк, создадим сессию и будем получать данные после авторизации. Как обычно код с комментариями, а потом небольшое разъяснение.

MainActivity.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.facebook.model.GraphUser;
import com.facebook.widget.LoginButton;

public class MainActivity extends Activity {

    //переменная которую мы будем использовать для авторизации
    private UiLifecycleHelper uiHelper;
    //наша кнопка для авторизации
    private LoginButton enterByFB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //обязательно почему то нужно это вписывать между super и 
        // setContentView, непонятно но факт, нужно делать именно так
        // statusCallback наша сессия которую мы запоминаем для дальнейшей работы
        uiHelper = new UiLifecycleHelper(this, statusCallback);
        uiHelper.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final TextView text = (TextView) findViewById(R.id.textView);
        //наша кнопка  по которой будем логиниться
        enterByFB = (LoginButton) findViewById(R.id.fb_login_button);
        enterByFB.setUserInfoChangedCallback(new LoginButton.UserInfoChangedCallback() {
            @Override
            public void onUserInfoFetched(GraphUser user) {
                if (user != null) {
                    //получаема имя и выводим в текст вью
                    text.setText(user.getName());
                }
            }
        });
    }

    // наша сессия она обрабатывает здесь возврат из диалога который появляется 
    // так же обрабатывает событие если приложение facebook установлено
    // и сдк обращается к нему и получает данные, в общем все происходит здесь
    private Session.StatusCallback statusCallback = new Session.StatusCallback() {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            if (state.isOpened()) {
                //здесь так же можно получить токен вот таким способом
                //session.getAccessToken();
                // и кучу всего еще можно получить из сесии
                Log.d("FacebookSampleActivity", "Facebook session opened");
            } else if (state.isClosed()) {
                Log.d("FacebookSampleActivity", "Facebook session closed");
            }
        }
    };

    //как только возвращаемся обратно запускаем обратно поток
    @Override
    public void onResume() {
        super.onResume();
        uiHelper.onResume();
    }

    // на паузе стопим все к чертям
    @Override
    public void onPause() {
        super.onPause();
        uiHelper.onPause();
    }

    //выходя гасите свет, убиваем процес что бы не палить електричество
    @Override
    public void onDestroy() {
        super.onDestroy();
        uiHelper.onDestroy();
    }

    //по возвращению обратно на активность передаем все полученные данные с диалога в колбек
    // и живем дальше счастливо
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        uiHelper.onActivityResult(requestCode, resultCode, data);
    }

    //при вращении экрана и т д сохраняем все что происходит на экране,
    // а то активити обычно обновляется. а диалог останется жив
    @Override
    public void onSaveInstanceState(Bundle savedState) {
        super.onSaveInstanceState(savedState);
        uiHelper.onSaveInstanceState(savedState);
    }
}


Вот собственно и все, код очень легкий, создали колбек в который передаем все что возвращает onActivityResult и выводим это на экран или запоминаем в префы \ базу. 

Все данные что вы хотите получать вы получаете здесь
enterByFB.setUserInfoChangedCallback(new LoginButton.UserInfoChangedCallback() {
            @Override
            public void onUserInfoFetched(GraphUser user) {
                if (user != null) {
                    //получаема имя и выводим в текст вью
                    text.setText(user.getName());
                }
            }
        });


В этом коллбеке вы можете вытащить все что угодно по юзеру, просто наберите user. и вам подскажет кучу методов которые возвращают те или иные данные.

Так как у меня стоит приложение фейсбука то по клику на кнопку — приложение автоматически заходит в аккаунт без каких либо махинаций





если же приложение не стоит то появится диалог и нужно будет вводить свои данные (старый скрин с предыдущей статьи)


Собственно и все что я хотел расказать и показать, спасибо за внимание.

Исходники
GitHub && DropBox