Авторизация ВКонтакте через WebView в Android приложении / Хабр
Здравствуй дорогой друг, в этой статье, на простом примере мы рассмотрим, каким образом можно реализовать авторизацию и использование api социальной сети «ВКонтакте» без подключения официального SDK. Пример приложения можно скачать на github по ссылке в конце статьи.
Создаем проект, подключаем зависимости
В проекте я буду использовать kotlin, mvvm, binding, navgraph подразумевается, что ты уже знаешь, что это такое 🙂
Создаем новый проект на основе Empty Activity, я назову его OAuthWithVK_Example
Создание нового проектаДобавляем в зависимости.
Зависимостиimplementation 'androidx.navigation:navigation-fragment-ktx:2.4.1' implementation 'androidx.navigation:navigation-ui-ktx:2.4.1' implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
Создаем необходимые классы и файлы
Создадим класс «App» расширяющий «Application», он будет представлять наше приложение и содержать экземпляр «AccountService» для хранения токена и экземпляр «Retrofit» с url для запросов к ВК api. Через companion object будем получать доступ к App и созданным экземплярам. По хорошему это нужно делать через DI, но для простоты примера сделаем так.
Класс App/** * Представляет приложение. */ class App : Application() { /** * Возвращает или устанавливает сервис хранения настроект. */ lateinit var accountService: IAccountService /** * Возвращает или устанавливает экземпляр ретрофита. */ lateinit var retrofit: Retrofit companion object { lateinit var application: App } override fun onCreate() { super.onCreate() application = this accountService = VKAccountService(getSharedPreferences("vk_account", MODE_PRIVATE)) retrofit = Retrofit.Builder() .baseUrl("https://api.vk.com/method/") .addConverterFactory(ScalarsConverterFactory.create()) .build() } }
Создадим интерфейс «IAccountService» и его реализацию «VKAccountService», сервис будет предоставлять возможность сохранять и получать token и userId.
Интерфейс IAccountService/** * Определяет интерфейс получения и установки параметров аккаунта. */ interface IAccountService { /** * Возвращает или устанавливает токен. */ var token: String? /** * Возвращает или устанавливает идентификатор пользователя. */ var userId: String? }Класс VKAccountService
/** * Представляет сервис сохранения пользовательских настроек. * @param sharedPreference Класс записи пользовательских настроек. */ internal class VKAccountService( private val sharedPreference: SharedPreferences ) : IAccountService { private val TOKEN = "token" private val USER_ID = "userId" companion object { const val SCOPE = "friends,stats" } override var token: String? get() { return sharedPreference.getString(TOKEN, null) } set(value) { with(sharedPreference.edit()) { if (value == null) { remove(TOKEN) } else { putString(TOKEN, value) } apply() } } override var userId: String? get() { return sharedPreference.getString(USER_ID, null) } set(value) { with(sharedPreference.edit()) { if (value == null) { remove(USER_ID) } else { putString(USER_ID, value) } apply() } } }
Создадим класс активити с именем «MainActivity» и соответствующий ему файл разметки «activity_main». Он будет содержать FragmentContainerView для навигации.
Класс MainActivity/** * Представляет основное активити приложения. */ class MainActivity : AppCompatActivity() { private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) setSupportActionBar(binding.toolbar) val navController = (supportFragmentManager. findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController appBarConfiguration = AppBarConfiguration(navController.graph) setupActionBarWithNavController(navController, appBarConfiguration) } override fun onSupportNavigateUp(): Boolean { val navController = findNavController(R.id.nav_host_fragment) return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() } }Файл разметки activity_main
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <androidx.appcompat.widget.LinearLayoutCompat android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/Theme.OpenAuthWithVK_Example.AppBarOverlay"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/Theme.OpenAuthWithVK_Example.PopupOverlay" /> </com.google.android.material.appbar.AppBarLayout> <androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" /> </androidx.appcompat.widget.LinearLayoutCompat> </layout>
Обновим файл манифеста, указав корневое активити.
Файл манифеста<manifest xmlns:android="http://schemas. android.com/apk/res/android" package="com.alab.oauthwithvk_example"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:name="com.alab.oauthwithvk_example.App" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true"> <activity android:name="com.alab.oauthwithvk_example.MainActivity" android:exported="true" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Для навигации по фрагментам понадобится файл «nav_graph».
Файл навигации<navigation xmlns:android="http://schemas. android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" app:startDestination="@id/AuthFragment"> <fragment android:id="@+id/AuthFragment" android:name="com.alab.oauthwithvk_example.AuthFragment" android:label="@string/auth_fragment_label"> <action android:id="@+id/action_AuthFragment_to_InfoFragment" app:destination="@id/InfoFragment" /> </fragment> <fragment android:id="@+id/InfoFragment" android:name="com.alab.oauthwithvk_example.InfoFragment" android:label="@string/info_fragment_label" tools:layout="@layout/info_fragment"> <action android:id="@+id/action_InfoFragment_to_AuthFragment" app:popUpTo="@id/AuthFragment" /> </fragment> </navigation>
Теперь создадим первый класс фрагмента для авторизации, назовем его «AuthFragment».
/** * Представляет фрагмент 'Войти в аккаунт'. */ class AuthFragment : Fragment() { private val webview by lazy { WebView(context!!) } private val _authParams = StringBuilder("https://oauth.vk.com/authorize?").apply { append(String.format("%s=%s", URLEncoder.encode("client_id", "UTF-8"), URLEncoder.encode(/*TODO Сюда вставить id приложения созданного в ВК в разделе "Developers"*/, "UTF-8")) + "&") append(String. format("%s=%s", URLEncoder.encode("redirect_uri", "UTF-8"), URLEncoder.encode("https://oauth.vk.com/blank.html", "UTF-8")) + "&") append(String.format("%s=%s", URLEncoder.encode("display", "UTF-8"), URLEncoder.encode("mobile", "UTF-8")) + "&") append(String.format("%s=%s", URLEncoder.encode("scope", "UTF-8"), URLEncoder.encode(VKAccountService.SCOPE, "UTF-8")) + "&") append(String.format("%s=%s", URLEncoder.encode("response_type", "UTF-8"), URLEncoder.encode("token", "UTF-8")) + "&") append(String.format("%s=%s", URLEncoder.encode("v", "UTF-8"), URLEncoder.encode("5.131", "UTF-8")) + "&") append(String.format("%s=%s", URLEncoder.encode("state", "UTF-8"), URLEncoder.encode("12345", "UTF-8")) + "&") append(String.format("%s=%s", URLEncoder.encode("revoke", "UTF-8"), URLEncoder.encode("1", "UTF-8"))) }.toString() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ) = webview override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) if (App.application.accountService.token == null) { webview.webViewClient = AuthWebViewClient(context!!) { status -> when(status) { AuthStatus.AUTH -> { } AuthStatus.CONFIRM -> { } AuthStatus.ERROR -> { Toast.makeText(context, "Не верный логин или пароль", Toast.LENGTH_LONG).show() } AuthStatus.BLOCKED -> { showAuthWindow() Toast.makeText(context, "Аккаунт заблокирован", Toast.LENGTH_LONG).show() } AuthStatus.SUCCESS -> { val url = webview.url!! val tokenMather = Pattern.compile("access_token=\\w+").matcher(url) val userIdMather = Pattern.compile("user_id=\\w+").matcher(url) // Если есть совпадение с патерном. if (tokenMather.find() && userIdMather.find()) { val token = tokenMather.group().replace("access_token=".toRegex(), "") val userId = userIdMather.group().replace("user_id=".toRegex(), "") // Если токен и id получен. if (token.isNotEmpty() && userId.isNotEmpty()) { App.application.accountService.token = token App.application.accountService.userId = userId navigateToInfo() } } } } } } else { navigateToInfo() } } override fun onStart() { super.onStart() if (App.application.accountService.token == null) { showAuthWindow() } } private fun showAuthWindow() { CookieManager. getInstance().removeAllCookies(null) webview.loadUrl(_authParams) } private fun navigateToInfo() { findNavController().navigate(R.id.action_AuthFragment_to_InfoFragment) } }
В зависимости от того какое событие сейчас происходит (ввод пароля, ошибка, заблокированный аккаунт), текущий url у WebView будет изменяться, на основе этого будем определять текущий статус аутентификации. Для этого создадим класс «AuthWebViewClient» расширяющий «WebViewClient», переопределим метод onPageFinished в котором будем парсить текущую открытую ссылку.
Класс AuthWebViewClient/** * Представляет WebView клиент. * @param context Контекст. * @param onStatusChange Обработчик смены статуса аутентификации. */ class AuthWebViewClient( private val context: Context, private val onStatusChange: (status: AuthStatus) -> Unit ) : WebViewClient() { private var _currentUrl = "" override fun shouldOverrideUrlLoading(wv: WebView, url: String): Boolean { wv. loadUrl(url) return true } override fun onPageFinished(wv: WebView, url: String) { if (_currentUrl != url) { val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager //если открыто окно аутентификации. if (url.contains("https://oauth.vk.com/authorize")) { val scope = URLEncoder.encode(VKAccountService.SCOPE, "UTF-8") // Если открыто окно ввода логина и пароля. if (url.contains(scope)) { imm.showSoftInput(wv, 0) wv.visibility = View.VISIBLE onStatusChange(AuthStatus.AUTH) } // Если открыто окно подтверждения разрешений. if (url.contains("q_hash")) { onStatusChange(AuthStatus.CONFIRM) } // Если открыто окно с сообщением об неверно введеном пароле. if (url.contains("email")) { onStatusChange(AuthStatus. ERROR) } } // Если открыто окно заблокированного пользователя. if (url.contains("https://m.vk.com/login\\?act=blocked")) { onStatusChange(AuthStatus.BLOCKED) } // Если открыто окно для считывания токена. if (url.contains("https://oauth.vk.com/blank.html")) { wv.visibility = View.INVISIBLE onStatusChange(AuthStatus.SUCCESS) } } _currentUrl = url } }
Перечислим статусы аутентификации в enum, который назовем «AuthStatus», этот enum будем передаваться кэлбеком из класса AuthWebViewClient во фрагмент.
Класс AuthStatus/** * Перечисляет статусы аутентификации клиента. */ enum class AuthStatus { /** * Статус ввода логина и пароля. */ AUTH, /** * Статус подтверждения разрешений. */ CONFIRM, /** * Статус завершения авторизации с ошибкой. */ ERROR, /** * Статус заблокированного пользователя. */ BLOCKED, /** * Статус успешного завершения авторизации. */ SUCCESS }
После верного ввода логина/пароля и подтверждения разрешений, будет получен и записан в память токен и идентификатор пользователя. С фрагментом аутентификации на этом все.
Приступим к созданию второго фрагмента, здесь мы сделаем всего 1 запрос на получение списка друзей. На экране покажем кнопку для выхода, textview для показа кол-ва друзей и скролящийся textview для показа списка друзей.
Создадим фрагмент с именем «InfoFragment» и соответствующий ему xml файл с разметкой «info_fragment».
Класс InfoFragment/** * Представляет фрагмент 'Инфо'. */ class InfoFragment : Fragment() { private val _viewModel: InfoViewModel by viewModels() private var _binding: InfoFragmentBinding? = null private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = InfoFragmentBinding. inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) with(binding) { lifecycleOwner = [email protected] vm = _viewModel tvFriends.movementMethod = ScrollingMovementMethod() logout.setOnClickListener { App.application.accountService.token = null App.application.accountService.userId = null findNavController().navigate(R.id.action_InfoFragment_to_AuthFragment) } } } override fun onDestroyView() { super.onDestroyView() _binding = null } }Файл разметки info_fragment
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="vm" type="com. alab.oauthwithvk_example.InfoViewModel" /> </data> <androidx.appcompat.widget.LinearLayoutCompat android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" android:orientation="vertical" tools:context=".InfoFragment"> <Button android:id="@+id/logout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Logout"/> <androidx.appcompat.widget.AppCompatTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text='@{"Друзей: " + vm.count}'/> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/tvFriends" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@{vm.friends}" android:layout_marginVertical="16dp" android:scrollbars="vertical"/> </androidx. appcompat.widget.LinearLayoutCompat> </layout>
Запрос на список друзей будем делать во ViewModel, эту вью модель передадим в биндинг, LiveData сама будет устанавливать данные в TextView.
Класс InfoViewModel/** * Определяет модель представления фрагмента 'Инфо'. */ class InfoViewModel: ViewModel() { private val _count = MutableLiveData<String>() private val _friends = MutableLiveData<String>() /** * Возвращает кол-во друзей. */ val count: LiveData<String> = _count /** * Возвращет список друзей. */ val friends: LiveData<String> = _friends init { viewModelScope.launch { val response = App.application.retrofit.create(FriendsGetRequest::class.java).friendsGet( App.application.accountService.token!!, "5.131", "name" ) val friendsList = StringBuilder() val items = JSONObject(response).getJSONObject("response").getJSONArray("items") for (i in 0 until items. length()) { friendsList.append( "${items.getJSONObject(i).getString("first_name")} ${items.getJSONObject(i).getString("last_name")}\n" ) } _count.postValue(JSONObject(response).getJSONObject("response").getString("count")) _friends.postValue(friendsList.toString()) } } }
Осталось написать интерфейс «FriendsGetRequest» с запросом для ретрофит и на этом с программной частью будем заканчивать 🙂
Интерфейс FriendsGetRequest/** * Определяет запрос друзей пользователя. */ interface FriendsGetRequest { /** * Возвращает json со списком друзей. */ @GET("friends.get") suspend fun friendsGet( @Query("access_token") token: String, @Query("v") v: String, @Query("fields") fields: String ): String }
Теперь разберемся, как получить client_id, это один из параметров запроса на авторизацию, его выдает ВК для понимания, какое приложение собирается обращаться к его api. Что бы его получить зайдите на свою страницу ВК и найдите меню «Управление», если его нет в списке, нужно добавить его в настройках страницы.
МенюКликнув по меню «Управление» мы попадем в раздел «Мои приложения», для создания нового приложения нажмите кнопку «Создать»
Раздел «Мои приложения»В открывшемся окне укажите название приложения и выберите тип «Standalone-приложение» далее жмем кнопку «Подключить приложение». После нажатия на кнопку, вам придет смс на подключенный к странице номер.
Создание приложенияКогда приложение будет создано перейдите в меню «Настройки», там будет указан client_id, который нужно вставить в код на место TODO, все остальные настройки по желанию 🙂
Меню настройки приложенияСкачать пример проекта можно здесь
Плеер Вконтакте (андроид 2.1) Мод apk скачать
Обновление от: 23.04.2019
Плеер Вконтакте (андроид 2.1) Мод представляет собой модифицированную версию плеера Вконтакте (андроид 2.1), разработанную Motorslomalsy. Вы можете скачать последнюю версию мода или оригинальную версию плеера Вконтакте (android 2.1) 1.4 с HappyMod. HappyMod — лучший загрузчик модов для 100% рабочих модов. Щелкните здесь, чтобы узнать, как использовать HappyMod для загрузки и установки всех типов файлов: xapk, bapk, apks…
Имя приложения | Плеер Вконтакте (android 2.1) Mod APK |
Обновление | 23.04.2019 |
Разработчик | Моторсломальсы |
Получить в Google Play | Игрок Вконтакте (android 2.1) |
Скачать оригинальный apk | Плеер Вконтакте (android 2.1) (0,26 МБ) |
Ссылки для скачивания: Плеер Вконтакте (android 2.1) Мод APKБыстрая загрузка ()Используйте приложение HappyMod, чтобы ускорить загрузку! Загрузить APK ()* Все apks мода загружаются пользователями. Если есть какие-либо нарушения, пожалуйста, свяжитесь с нами, чтобы удалить его. |
+Table Of Contents
# Информация о моде плеера Вконтакте (android 2.1) mod apk
# Как скачать и установить плеер Вконтакте (андроид 2.1) mod apk
# Полные характеристики плеера Вконтакте (андроид 2.1) мод apk
# Комментарии пользователей плеера Вконтакте (андроид 2.1) mod apk
# Видео захвата экрана плеера Вконтакте (андроид 2.1) мод apk
Основные преимущества/модификации плеера Вконтакте (андроид 2.1) Мод APK
Мод рекомендации
Мод последней версии
// Вариант А //
Скачать мод плеера Вконтакте (андроид 2.1) с сайта HappyMod.com.
Вам необходимо включить опцию «Неизвестные источники».
1. Нажмите на ссылку выше, чтобы скачать мод APK плеера Вконтакте (android 2.1).
2. Сохраните файл в папке «Загрузки» вашего устройства.
3. Теперь нажмите «Установить» и дождитесь завершения установки.
4. Как только это будет сделано, откройте игру и сразу же начните играть.
// Вариант Б //
Чтобы скачать плеер Вконтакте (android 2.1) из приложения HappyMod, выполните следующие действия:
1. Откройте браузер и загрузите APK-файл HappyMod с HappyMod.com — единственного официального сайта HappyMod.
2. Откройте настройки Android и перейдите в раздел «Конфиденциальность» или «Безопасность».
3. Коснитесь параметра «Разрешить неизвестные источники» и включите его.
4. Перейдите к загрузкам Android и коснитесь файла APK.
5. Следуйте инструкциям на экране, чтобы установить его.
6. Найдите плеер Вконтакте (android 2.1) в приложении HappyMod.
// Загрузить информацию //
Подробнее…[+]
// Операционные системы //
Многооконный | № |
Поддерживает экраны | |
Open GL Int | |
Поддерживает любую плотность | Нет |
Лучший загрузчик модов |
Скачать Apk
Плеер Вконтакте (android 2.1) Мод apk ~ качайте быстрее с HappyMod.
Найдены () версии плеера Вконтакте (андроид 2.1) Мод
Людям, скачивающим плеер Вконтакте (андроид 2.1) Мод тоже нравится…
Подробнее…[+]
Стрим ВК для ПК (Windows и MAC)
Вы здесь: Главная / Программы для ПК / Стрим ВКонтакте для ПК (Windows и MAC)
от Hasan Abbas Оставить комментарий
Загрузите VK Stream для ПК/Mac/Windows 7,8,10 и получите удовольствие от использования приложений для смартфонов на рабочем столе или персональных компьютерах.
Новое и развивающееся приложение, VK Stream , разработанное Amberfog для Android, доступно бесплатно в Play Store. VK Stream имеет последнюю версию 1.68.241, которая последний раз обновлялась 28.05.19. Прежде чем мы перейдем к руководству по установке VK Stream на ПК с помощью эмуляторов, вы можете зайти в официальный магазин Play, чтобы узнать, что они предлагают. Там вы можете прочитать полные функции и описание приложения.
Еще от нас: Pearltrees для ПК (Windows и MAC).
Содержание
- 0.1 Информация о трансляции ВКонтакте
- 1 Информация о трансляции ВКонтакте на ПК (Windows / MAC)
Информация о трансляции ВКонтакте
Имя: | ВК Стрим |
Разработчики: | Янтарный туман |
Текущая версия: | 1.68.241 |
Последнее обновление: | 28. 05.19 |
Сегодня мы покажем вам, как скачать и установить VK Stream на ПК под управлением любой ОС, включая варианты Windows и MAC , однако, если вас интересуют другие приложения, посетите наш сайт about Приложения для Android на ПК и найдите свои любимые, без лишних слов, давайте продолжим.
VK Stream на ПК (Windows/MAC)- Загрузите и установите Android Emulator для ПК по вашему выбору из списка, который мы предоставили.
- Откройте установленный эмулятор и откройте в нем Google Play Store.
- Теперь найдите « VK Stream » с помощью Play Store.
- Установите игру и откройте панель приложений или все приложения в эмуляторе.
- Щелкните значок VK Stream , чтобы открыть его, следуйте инструкциям на экране, чтобы воспроизвести его.
- Вы также можете скачать VK Stream APK и установить через APK в эмуляторе Android BlueStacks.