Android и VKontakte SDK, часть 3 (авторизация и получение прав)

Во второй части я описал, как получить авторизацию от vk не используя сторонних библиотек и sdk. Недостаток данного способа в том, что каждому новому пользователю приходится вводить логин и пароль социальной сети. Время идет и вот vkontakte создает свою sdk для android! С помощью нее можно легко получить токен авторизации пользователя не вводя ни каких данных и даже не видя самого окна запроса прав.

Для начала нужно подключить Android VK SDK к вашему проекту и по пунктам выполнить все действия из официальной документации SDK по настройке и подключению, а именно: "Подготовка к использованию VK SDK", "Как получить отпечаток сертификата", "Подключение VK SDK в Android-приложении".

Далее создаем activity с авторизацией:

public class VKontakteActivity extends Activity {

    //Token auth
    private VKAccessToken access_token;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.progress);

        //Получаем токен
        access_token = VKAccessToken.tokenFromSharedPreferences(this, "VK_ACCESS_TOKEN");

        //Инициализируем
        VKSdk.initialize(new VKSdkListener() {
            @Override
            public void onCaptchaError(VKError captchaError) {
                new VKCaptchaDialog(captchaError).show();
                Log.d("onCaptchaError");
            }

            @Override
            public void onTokenExpired(VKAccessToken expiredToken) {
                Log.d("onTokenExpired");
                VKSdk.authorize();
            }

            @Override
            public void onAccessDenied(VKError authorizationError) {
                new AlertDialog.Builder(VKontakteActivity.this).setMessage(authorizationError.errorMessage).show();
            }

            @Override
            public void onReceiveNewToken(VKAccessToken token) {
                access_token = token;
                access_token.saveTokenToSharedPreferences(VKontakteActivity.this, "VK_ACCESS_TOKEN");
                getMeInfo();
            }
        }, vk_app_id, access_token);

        //Сохраняем активити
        VKUIHelper.onResume(this);

        //Запускаем авторизацию
        Log.w("access_token: " + access_token);
        VKSdk.authorize();
    }

    //Получение информации о юзере
    private void getMeInfo() {

        //Подготавливаем запрос
        VKApi.users().get().executeWithListener(new VKRequest.VKRequestListener() {

            @Override
            public void onComplete(VKResponse response) {
                try {
                    JSONObject r = response.json.getJSONArray("response").getJSONObject(0);
                    // Здесь обрабатываем полученный response.
                    Log.d("response: " + r);
                    Intent intent = new Intent();
                    intent.putExtra("provider", "vkontakte");
                    intent.putExtra("access_token", access_token.accessToken);
                    intent.putExtra("uid", r.getString("id"));
                    intent.putExtra("email", "");
                    intent.putExtra("first_name", r.getString("first_name"));
                    intent.putExtra("last_name", r.getString("last_name"));
                    setResult(RESULT_OK, intent);
                } catch( JSONException e ) {
                    Log.e(e.getMessage(), e);
                }
                finish();
            }

            @Override
            public void onProgress(VKRequest.VKProgressType progressType, long bytesLoaded, long bytesTotal) {
                super.onProgress(progressType, bytesLoaded, bytesTotal);
                Log.d("progress: " + progressType);
            }

            @Override
            public void onError(VKError error) {
                new AlertDialog.Builder(VKontakteActivity.this).setMessage(error.errorMessage).show();
            }
            @Override
            public void attemptFailed(VKRequest request, int attemptNumber, int totalAttempts) {
                // Неудачная попытка. В аргументах имеется номер попытки и общее их количество.
                Log.w("attemptFailed");
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        VKUIHelper.onDestroy(this);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.d(getClass().getName() + ".onActivityResult and resultCode = " + resultCode + ", requestCode = " + requestCode);
        VKUIHelper.onActivityResult(requestCode, resultCode, data);
        if( resultCode == RESULT_CANCELED ) {
            finish();
        }
    }
}

Вместо переменной vk_app_id нужно вписать свой ID приложения ВКонтакте. Данный экран выполняет все необходимые действия по получению токена и необходимой информации о пользователе. Использовать данных экран достаточно просто, допустим мы имеем некую кнопку, при нажатии на которую будет происходить авторизация:

vkontakte.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        startActivityForResult(new Intent(this, VKontakteActivity.class), VKONTAKTE_CODE);
    }
});

VKONTAKTE_CODE - любое число, по которому будет происходить проверка в функции onActivityResult в переменной requestCode, что ответ пришел именно от нужного нам экрана, тем самым фильтровать логику ответов различных экранов (допустим, когда у нас несколько кнопок авторизации разных соц. сетей).

Данный код нужно расместить в любом месте вашего основного экрана, в мое случае это было в методе onCreate класса LoginActivity. Все полученные данные из экрана VKontakteActivity попадут в функцию onActivityResult основного экрана вашего приложения, т.е. откуда VKontakteActivity было запущено:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    //Если успешно
    if( requestCode == VKONTAKTE_CODE && resultCode == Activity.RESULT_OK ) {
        //Так же по аналогии и все переданные данные из VKontakteActivity
        Log.d(TAG, data.getStringExtra("access_token"));
    }
}

Данный способ существенно упрощает жизнь всем вашим пользователям, т.к. не заставляет вводить лишние данные при авторизации. Если вдруг у пользователя нет приложения ВКонтакте на телефоне, то vk sdk откроет страницу авторизации в обычном webview и сделает все, что было описано во второй части.

P.Nixx, 26.03.2015, 15:00