{"id":330040,"date":"2022-02-23T21:00:17","date_gmt":"2022-02-23T21:00:17","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=330040"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=330040","title":{"rendered":"<span>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 WebView \u0432 Android \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439 \u0434\u043e\u0440\u043e\u0433\u043e\u0439 \u0434\u0440\u0443\u0433, \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 api \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 &#171;\u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435&#187;  \u0431\u0435\u0437 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e SDK. \u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u043d\u0430 github \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<h4>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/h4>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c kotlin, mvvm, binding, navgraph \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0442\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u0448\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \ud83d\ude42<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Empty Activity, \u044f \u043d\u0430\u0437\u043e\u0432\u0443 \u0435\u0433\u043e OAuthWithVK_Example <\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/287\/70b\/60c\/28770b60c052fe684696fa2997b2257b.jpg\" width=\"902\" height=\"650\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/287\/70b\/60c\/28770b60c052fe684696fa2997b2257b.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/078\/0ce\/78a\/0780ce78a0b24ffe19b2c8998bdc416d.jpg\" width=\"902\" height=\"650\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/078\/0ce\/78a\/0780ce78a0b24ffe19b2c8998bdc416d.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<\/div>\n<\/details>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">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'<\/code><\/pre>\n<\/div>\n<\/details>\n<h4>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u0444\u0430\u0439\u043b\u044b<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 &#171;App&#187; \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u0439 &#171;Application&#187;, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 &#171;AccountService&#187; \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0438  \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 &#171;Retrofit&#187; \u0441 url \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0412\u041a api. \u0427\u0435\u0440\u0435\u0437 companion object \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a App \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c. \u041f\u043e \u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 DI, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 App<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.  *\/ class App : Application() {     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a\u0442.      *\/     lateinit var accountService: IAccountService      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0440\u0435\u0442\u0440\u043e\u0444\u0438\u0442\u0430.      *\/     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()     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 &#171;IAccountService&#187; \u0438 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e &#171;VKAccountService&#187;, \u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c token \u0438 userId.<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IAccountService<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430.  *\/ interface IAccountService {     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d.      *\/     var token: String?     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.      *\/     var userId: String? }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 VKAccountService<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.  * @param sharedPreference \u041a\u043b\u0430\u0441\u0441 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.  *\/ 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()             }         } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 \u0430\u043a\u0442\u0438\u0432\u0438\u0442\u0438 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c &#171;MainActivity&#187; \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0435\u043c\u0443 \u0444\u0430\u0439\u043b \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 &#171;activity_main&#187;. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c FragmentContainerView \u0434\u043b\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 MainActivity<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0442\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.  *\/ 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()     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0424\u0430\u0439\u043b \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 activity_main<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">&lt;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\">      &lt;androidx.appcompat.widget.LinearLayoutCompat         android:layout_width=\"match_parent\"         android:layout_height=\"match_parent\"         android:orientation=\"vertical\"         tools:context=\".MainActivity\">          &lt;com.google.android.material.appbar.AppBarLayout             android:layout_width=\"match_parent\"             android:layout_height=\"wrap_content\"             android:theme=\"@style\/Theme.OpenAuthWithVK_Example.AppBarOverlay\">              &lt;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\" \/>          &lt;\/com.google.android.material.appbar.AppBarLayout>          &lt;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\" \/>      &lt;\/androidx.appcompat.widget.LinearLayoutCompat>  &lt;\/layout><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041e\u0431\u043d\u043e\u0432\u0438\u043c \u0444\u0430\u0439\u043b \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430, \u0443\u043a\u0430\u0437\u0430\u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0442\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0424\u0430\u0439\u043b \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">&lt;manifest xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"     package=\"com.alab.oauthwithvk_example\">      &lt;uses-permission android:name=\"android.permission.INTERNET\" \/>      &lt;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\">         &lt;activity             android:name=\"com.alab.oauthwithvk_example.MainActivity\"             android:exported=\"true\"             android:label=\"@string\/app_name\">             &lt;intent-filter>                 &lt;action android:name=\"android.intent.action.MAIN\" \/>                  &lt;category android:name=\"android.intent.category.LAUNCHER\" \/>             &lt;\/intent-filter>         &lt;\/activity>     &lt;\/application>  &lt;\/manifest><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0444\u0430\u0439\u043b &#171;nav_graph&#187;.<\/p>\n<details class=\"spoiler\">\n<summary>\u0424\u0430\u0439\u043b \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">&lt;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\">      &lt;fragment         android:id=\"@+id\/AuthFragment\"         android:name=\"com.alab.oauthwithvk_example.AuthFragment\"         android:label=\"@string\/auth_fragment_label\">          &lt;action             android:id=\"@+id\/action_AuthFragment_to_InfoFragment\"             app:destination=\"@id\/InfoFragment\" \/>     &lt;\/fragment>      &lt;fragment         android:id=\"@+id\/InfoFragment\"         android:name=\"com.alab.oauthwithvk_example.InfoFragment\"         android:label=\"@string\/info_fragment_label\"         tools:layout=\"@layout\/info_fragment\">          &lt;action             android:id=\"@+id\/action_InfoFragment_to_AuthFragment\"             app:popUpTo=\"@id\/AuthFragment\" \/>     &lt;\/fragment>  &lt;\/navigation><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e &#171;AuthFragment&#187;. \u0417\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0438\u0434\u0436\u0435\u0442 WebView, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e. \u0414\u043b\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u043e\u043a\u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0443\u0436\u0435\u043d url \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438, \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c &#171;_authParams&#187;, \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439, \u0434\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0435\u0435 \u0432 WebView. \u0412 \u043c\u0435\u0442\u043e\u0434\u0435 onViewCreated \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043e\u043a\u043d\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f &#8216;\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439&#8217;, &#8216;\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430 \u043b\u043e\u0433\u0438\u043d\u0430\/\u043f\u0430\u0440\u043e\u043b\u044f&#8217;, &#8216;\u0423\u0441\u043f\u0435\u0445&#8217; \u0438 \u0434\u0440. \u0412 \u043a\u043e\u0434\u0435 \u044f \u043e\u0441\u0442\u0430\u0432\u0438\u043b TODO \u043a\u0443\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0430\u0448 client_id \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u0430\u043a \u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 AuthFragment<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 '\u0412\u043e\u0439\u0442\u0438 \u0432 \u0430\u043a\u043a\u0430\u0443\u043d\u0442'.  *\/ 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 \u0421\u044e\u0434\u0430 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c id \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0412\u041a \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \"Developers\"*\/, \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"redirect_uri\", \"UTF-8\"), URLEncoder.encode(\"https:\/\/oauth.vk.com\/blank.html\", \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"display\", \"UTF-8\"), URLEncoder.encode(\"mobile\", \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"scope\", \"UTF-8\"), URLEncoder.encode(VKAccountService.SCOPE, \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"response_type\", \"UTF-8\"), URLEncoder.encode(\"token\", \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"v\", \"UTF-8\"), URLEncoder.encode(\"5.131\", \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"state\", \"UTF-8\"), URLEncoder.encode(\"12345\", \"UTF-8\")) + \"&amp;\")         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, \"\u041d\u0435 \u0432\u0435\u0440\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u043d \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c\", Toast.LENGTH_LONG).show()                     }                     AuthStatus.BLOCKED -> {                         showAuthWindow()                         Toast.makeText(context, \"\u0410\u043a\u043a\u0430\u0443\u043d\u0442 \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\", 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)                         \/\/ \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0441 \u043f\u0430\u0442\u0435\u0440\u043d\u043e\u043c.                         if (tokenMather.find() &amp;&amp; userIdMather.find()) {                             val token = tokenMather.group().replace(\"access_token=\".toRegex(), \"\")                             val userId = userIdMather.group().replace(\"user_id=\".toRegex(), \"\")                             \/\/ \u0415\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0438 id \u043f\u043e\u043b\u0443\u0447\u0435\u043d.                             if (token.isNotEmpty() &amp;&amp; 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)     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e \u043a\u0430\u043a\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 (\u0432\u0432\u043e\u0434 \u043f\u0430\u0440\u043e\u043b\u044f, \u043e\u0448\u0438\u0431\u043a\u0430, \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442), \u0442\u0435\u043a\u0443\u0449\u0438\u0439 url \u0443 WebView \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 &#171;AuthWebViewClient&#187; \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u0439 &#171;WebViewClient&#187;, \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043c\u0435\u0442\u043e\u0434 onPageFinished \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043e\u0442\u043a\u0440\u044b\u0442\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 AuthWebViewClient<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 WebView \u043a\u043b\u0438\u0435\u043d\u0442.  * @param context \u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442.  * @param onStatusChange \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043c\u0435\u043d\u044b \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.  *\/ 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             \/\/\u0435\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e \u043e\u043a\u043d\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.             if (url.contains(\"https:\/\/oauth.vk.com\/authorize\")) {                 val scope = URLEncoder.encode(VKAccountService.SCOPE, \"UTF-8\")                 \/\/ \u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e \u043e\u043a\u043d\u043e \u0432\u0432\u043e\u0434\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.                 if (url.contains(scope)) {                     imm.showSoftInput(wv, 0)                     wv.visibility = View.VISIBLE                     onStatusChange(AuthStatus.AUTH)                 }                 \/\/ \u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e \u043e\u043a\u043d\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439.                 if (url.contains(\"q_hash\")) {                     onStatusChange(AuthStatus.CONFIRM)                 }                 \/\/ \u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e \u043e\u043a\u043d\u043e \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c \u043e\u0431 \u043d\u0435\u0432\u0435\u0440\u043d\u043e \u0432\u0432\u0435\u0434\u0435\u043d\u043e\u043c \u043f\u0430\u0440\u043e\u043b\u0435.                 if (url.contains(\"email\")) {                     onStatusChange(AuthStatus.ERROR)                 }             }             \/\/ \u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e \u043e\u043a\u043d\u043e \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.             if (url.contains(\"https:\/\/m.vk.com\/login\\\\?act=blocked\")) {                 onStatusChange(AuthStatus.BLOCKED)             }             \/\/ \u0415\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u043e \u043e\u043a\u043d\u043e \u0434\u043b\u044f \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430.             if (url.contains(\"https:\/\/oauth.vk.com\/blank.html\")) {                 wv.visibility = View.INVISIBLE                 onStatusChange(AuthStatus.SUCCESS)             }         }         _currentUrl = url     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0438\u043c \u0441\u0442\u0430\u0442\u0443\u0441\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 enum, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0437\u043e\u0432\u0435\u043c &#171;AuthStatus&#187;, \u044d\u0442\u043e\u0442 enum \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u044d\u043b\u0431\u0435\u043a\u043e\u043c \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u0430 AuthWebViewClient \u0432\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 AuthStatus<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u0441\u0442\u0430\u0442\u0443\u0441\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430.  *\/ enum class AuthStatus {     \/**      * \u0421\u0442\u0430\u0442\u0443\u0441 \u0432\u0432\u043e\u0434\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.      *\/     AUTH,     \/**      * \u0421\u0442\u0430\u0442\u0443\u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439.      *\/     CONFIRM,     \/**      * \u0421\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439.      *\/     ERROR,     \/**      * \u0421\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.      *\/     BLOCKED,     \/**      * \u0421\u0442\u0430\u0442\u0443\u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.      *\/     SUCCESS }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430 \u043b\u043e\u0433\u0438\u043d\u0430\/\u043f\u0430\u0440\u043e\u043b\u044f \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439, \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u043d \u0432 \u043f\u0430\u043c\u044f\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0421 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435.<\/p>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430, \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0432\u0441\u0435\u0433\u043e 1 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u0440\u0443\u0437\u0435\u0439. \u041d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u043f\u043e\u043a\u0430\u0436\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u0432\u044b\u0445\u043e\u0434\u0430, textview \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u043a\u043e\u043b-\u0432\u0430 \u0434\u0440\u0443\u0437\u0435\u0439 \u0438 \u0441\u043a\u0440\u043e\u043b\u044f\u0449\u0438\u0439\u0441\u044f textview \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u0440\u0443\u0437\u0435\u0439.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c &#171;InfoFragment&#187; \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0435\u043c\u0443 xml \u0444\u0430\u0439\u043b \u0441 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u043e\u0439 &#171;info_fragment&#187;.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 InfoFragment<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 '\u0418\u043d\u0444\u043e'.  *\/ 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 = this@InfoFragment.viewLifecycleOwner             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     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0424\u0430\u0439\u043b \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 info_fragment<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">&lt;layout     xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"     xmlns:tools=\"http:\/\/schemas.android.com\/tools\">      &lt;data>         &lt;variable             name=\"vm\"             type=\"com.alab.oauthwithvk_example.InfoViewModel\" \/>     &lt;\/data>      &lt;androidx.appcompat.widget.LinearLayoutCompat         android:layout_width=\"match_parent\"         android:layout_height=\"match_parent\"         android:padding=\"16dp\"         android:orientation=\"vertical\"         tools:context=\".InfoFragment\">          &lt;Button             android:id=\"@+id\/logout\"             android:layout_width=\"wrap_content\"             android:layout_height=\"wrap_content\"             android:text=\"Logout\"\/>          &lt;androidx.appcompat.widget.AppCompatTextView             android:layout_width=\"match_parent\"             android:layout_height=\"wrap_content\"             android:text='@{\"\u0414\u0440\u0443\u0437\u0435\u0439: \" + vm.count}'\/>          &lt;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\"\/>      &lt;\/androidx.appcompat.widget.LinearLayoutCompat>  &lt;\/layout><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0440\u0443\u0437\u0435\u0439 \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u043e ViewModel, \u044d\u0442\u0443 \u0432\u044c\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0432 \u0431\u0438\u043d\u0434\u0438\u043d\u0433, LiveData \u0441\u0430\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 TextView.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 InfoViewModel<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430 '\u0418\u043d\u0444\u043e'.  *\/ class InfoViewModel: ViewModel() {     private val _count = MutableLiveData&lt;String>()     private val _friends = MutableLiveData&lt;String>()      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043b-\u0432\u043e \u0434\u0440\u0443\u0437\u0435\u0439.      *\/     val count: LiveData&lt;String> = _count      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0440\u0443\u0437\u0435\u0439.      *\/     val friends: LiveData&lt;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())         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 &#171;FriendsGetRequest&#187; \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u0434\u043b\u044f \u0440\u0435\u0442\u0440\u043e\u0444\u0438\u0442 \u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u0441 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0442\u044c \ud83d\ude42<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 FriendsGetRequest<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u0440\u0443\u0437\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.  *\/ interface FriendsGetRequest {     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 json \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0434\u0440\u0443\u0437\u0435\u0439.      *\/     @GET(\"friends.get\")     suspend fun friendsGet(         @Query(\"access_token\") token: String,         @Query(\"v\") v: String,         @Query(\"fields\") fields: String     ): String }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c client_id, \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u0435\u0433\u043e \u0432\u044b\u0434\u0430\u0435\u0442 \u0412\u041a \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f, \u043a\u0430\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f  \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0435\u0433\u043e api. \u0427\u0442\u043e \u0431\u044b \u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u0430\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0441\u0432\u043e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0412\u041a \u0438 \u043d\u0430\u0439\u0434\u0438\u0442\u0435 \u043c\u0435\u043d\u044e &#171;\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435&#187;, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u043d\u0435\u0442 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435, \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u0435\u043d\u044e<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/ef2\/6be\/bb5\/ef26bebb563e6de596ee44529eb8f9b4.jpg\" width=\"195\" height=\"235\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ef2\/6be\/bb5\/ef26bebb563e6de596ee44529eb8f9b4.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<\/div>\n<\/details>\n<p>\u041a\u043b\u0438\u043a\u043d\u0443\u0432 \u043f\u043e \u043c\u0435\u043d\u044e &#171;\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435&#187; \u043c\u044b \u043f\u043e\u043f\u0430\u0434\u0435\u043c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b &#171;\u041c\u043e\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f&#187;, \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;\u0421\u043e\u0437\u0434\u0430\u0442\u044c&#187;<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0430\u0437\u0434\u0435\u043b &#171;\u041c\u043e\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f&#187;<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/f87\/e93\/4e2\/f87e934e2dfebdaa64b1cdf19843e46d.jpg\" width=\"980\" height=\"374\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f87\/e93\/4e2\/f87e934e2dfebdaa64b1cdf19843e46d.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<\/div>\n<\/details>\n<p>\u0412 \u043e\u0442\u043a\u0440\u044b\u0432\u0448\u0435\u043c\u0441\u044f \u043e\u043a\u043d\u0435 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f &#171;Standalone-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435&#187; \u0434\u0430\u043b\u0435\u0435 \u0436\u043c\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 &#171;\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435&#187;. \u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443, \u0432\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442 \u0441\u043c\u0441 \u043d\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0439 \u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u043e\u043c\u0435\u0440.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/13c\/c55\/2aa\/13cc552aa03bec8440319d48f1ceb402.jpg\" width=\"1015\" height=\"444\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/13c\/c55\/2aa\/13cc552aa03bec8440319d48f1ceb402.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<\/div>\n<\/details>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043e \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043c\u0435\u043d\u044e &#171;\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438&#187;, \u0442\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d client_id, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u043e\u0434 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e TODO, \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e \ud83d\ude42<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u0435\u043d\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/5ea\/247\/531\/5ea2475317bda25301732ed154a37a4e.jpg\" width=\"973\" height=\"369\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5ea\/247\/531\/5ea2475317bda25301732ed154a37a4e.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<\/div>\n<\/details>\n<p><a href=\"https:\/\/github.com\/AndroidLab\/OAuthWithVK_Example\" rel=\"noopener noreferrer nofollow\">\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/653201\/\"> https:\/\/habr.com\/ru\/post\/653201\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439 \u0434\u043e\u0440\u043e\u0433\u043e\u0439 \u0434\u0440\u0443\u0433, \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 api \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 &#171;\u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435&#187;  \u0431\u0435\u0437 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e SDK. \u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u043d\u0430 github \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<h4>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/h4>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c kotlin, mvvm, binding, navgraph \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0442\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u0448\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \ud83d\ude42<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Empty Activity, \u044f \u043d\u0430\u0437\u043e\u0432\u0443 \u0435\u0433\u043e OAuthWithVK_Example <\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<\/div>\n<\/details>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">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'<\/code><\/pre>\n<\/div>\n<\/details>\n<h4>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u0444\u0430\u0439\u043b\u044b<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 &#171;App&#187; \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u0439 &#171;Application&#187;, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 &#171;AccountService&#187; \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0438  \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 &#171;Retrofit&#187; \u0441 url \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0412\u041a api. \u0427\u0435\u0440\u0435\u0437 companion object \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a App \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c. \u041f\u043e \u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 DI, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 App<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.  *\/ class App : Application() {     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a\u0442.      *\/     lateinit var accountService: IAccountService      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0440\u0435\u0442\u0440\u043e\u0444\u0438\u0442\u0430.      *\/     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()     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 &#171;IAccountService&#187; \u0438 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e &#171;VKAccountService&#187;, \u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c token \u0438 userId.<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IAccountService<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430.  *\/ interface IAccountService {     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d.      *\/     var token: String?     \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.      *\/     var userId: String? }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 VKAccountService<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.  * @param sharedPreference \u041a\u043b\u0430\u0441\u0441 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.  *\/ 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()             }         } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 \u0430\u043a\u0442\u0438\u0432\u0438\u0442\u0438 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c &#171;MainActivity&#187; \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0435\u043c\u0443 \u0444\u0430\u0439\u043b \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 &#171;activity_main&#187;. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c FragmentContainerView \u0434\u043b\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 MainActivity<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0442\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.  *\/ 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()     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0424\u0430\u0439\u043b \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 activity_main<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">&lt;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\">      &lt;androidx.appcompat.widget.LinearLayoutCompat         android:layout_width=\"match_parent\"         android:layout_height=\"match_parent\"         android:orientation=\"vertical\"         tools:context=\".MainActivity\">          &lt;com.google.android.material.appbar.AppBarLayout             android:layout_width=\"match_parent\"             android:layout_height=\"wrap_content\"             android:theme=\"@style\/Theme.OpenAuthWithVK_Example.AppBarOverlay\">              &lt;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\" \/>          &lt;\/com.google.android.material.appbar.AppBarLayout>          &lt;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\" \/>      &lt;\/androidx.appcompat.widget.LinearLayoutCompat>  &lt;\/layout><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041e\u0431\u043d\u043e\u0432\u0438\u043c \u0444\u0430\u0439\u043b \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430, \u0443\u043a\u0430\u0437\u0430\u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0442\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0424\u0430\u0439\u043b \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">&lt;manifest xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"     package=\"com.alab.oauthwithvk_example\">      &lt;uses-permission android:name=\"android.permission.INTERNET\" \/>      &lt;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\">         &lt;activity             android:name=\"com.alab.oauthwithvk_example.MainActivity\"             android:exported=\"true\"             android:label=\"@string\/app_name\">             &lt;intent-filter>                 &lt;action android:name=\"android.intent.action.MAIN\" \/>                  &lt;category android:name=\"android.intent.category.LAUNCHER\" \/>             &lt;\/intent-filter>         &lt;\/activity>     &lt;\/application>  &lt;\/manifest><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u043f\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0444\u0430\u0439\u043b &#171;nav_graph&#187;.<\/p>\n<details class=\"spoiler\">\n<summary>\u0424\u0430\u0439\u043b \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">&lt;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\">      &lt;fragment         android:id=\"@+id\/AuthFragment\"         android:name=\"com.alab.oauthwithvk_example.AuthFragment\"         android:label=\"@string\/auth_fragment_label\">          &lt;action             android:id=\"@+id\/action_AuthFragment_to_InfoFragment\"             app:destination=\"@id\/InfoFragment\" \/>     &lt;\/fragment>      &lt;fragment         android:id=\"@+id\/InfoFragment\"         android:name=\"com.alab.oauthwithvk_example.InfoFragment\"         android:label=\"@string\/info_fragment_label\"         tools:layout=\"@layout\/info_fragment\">          &lt;action             android:id=\"@+id\/action_InfoFragment_to_AuthFragment\"             app:popUpTo=\"@id\/AuthFragment\" \/>     &lt;\/fragment>  &lt;\/navigation><\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e &#171;AuthFragment&#187;. \u0417\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0438\u0434\u0436\u0435\u0442 WebView, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e. \u0414\u043b\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u043e\u043a\u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0443\u0436\u0435\u043d url \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438, \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c &#171;_authParams&#187;, \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439, \u0434\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0435\u0435 \u0432 WebView. \u0412 \u043c\u0435\u0442\u043e\u0434\u0435 onViewCreated \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043e\u043a\u043d\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f &#8216;\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439&#8217;, &#8216;\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430 \u043b\u043e\u0433\u0438\u043d\u0430\/\u043f\u0430\u0440\u043e\u043b\u044f&#8217;, &#8216;\u0423\u0441\u043f\u0435\u0445&#8217; \u0438 \u0434\u0440. \u0412 \u043a\u043e\u0434\u0435 \u044f \u043e\u0441\u0442\u0430\u0432\u0438\u043b TODO \u043a\u0443\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0430\u0448 client_id \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u0430\u043a \u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 AuthFragment<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">\/**  * \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 '\u0412\u043e\u0439\u0442\u0438 \u0432 \u0430\u043a\u043a\u0430\u0443\u043d\u0442'.  *\/ 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 \u0421\u044e\u0434\u0430 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c id \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0412\u041a \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \"Developers\"*\/, \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"redirect_uri\", \"UTF-8\"), URLEncoder.encode(\"https:\/\/oauth.vk.com\/blank.html\", \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"display\", \"UTF-8\"), URLEncoder.encode(\"mobile\", \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"scope\", \"UTF-8\"), URLEncoder.encode(VKAccountService.SCOPE, \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"response_type\", \"UTF-8\"), URLEncoder.encode(\"token\", \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"v\", \"UTF-8\"), URLEncoder.encode(\"5.131\", \"UTF-8\")) + \"&amp;\")         append(String.format(\"%s=%s\", URLEncoder.encode(\"state\", \"UTF-8\"),<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-330040","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330040","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=330040"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330040\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=330040"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=330040"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=330040"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}