Day19 Plugin 从零开始到上架 - 取得授权码(Android)

目标

取得INSTAGRAM_CLIENT_ID、INSTAGRAM_CLIENT_SECRET 和 REDIRECT_URI 後,我们就要透过这些资料拿到Instagram 用户存取权杖,流程参考官方文件,所以我们要先开一个WebView,来取得短期权杖最後所需要的授权码code,之後再透过此授权码就能打api来取得短期权杖了

Android端

新建一个Activity AccessTokenActivity,来取得权杖,首先须先把之前取得资讯传进AccessTokenActivity,在WebView 透过之前取得的资讯,在使用者点选正确流程後,即可取得授权码,之後再透过viewModel 来取得短期权杖(下一篇内容)

class AccessTokenActivity : AppCompatActivity() {

    private lateinit var clientId: String
    private lateinit var clientSecret: String
    private lateinit var redirectUri: String

    private val viewModel: AccessTokenViewModel by viewModel()

    private val webView: WebView by lazy {
        findViewById<WebView>(R.id.webView)
    }
    
    companion object {
        private const val CLIENT_ID_EXTRA = "client_id"
        private const val CLIENT_SECRET_EXTRA = "client_secret"
        private const val REDIRECT_URI_EXTRA = "redirect_uri"

        fun createIntent(
            context: Context,
            clientId: String,
            clientSecret: String,
            redirectUri: String
        ): Intent {
            return Intent(context, AccessTokenActivity::class.java)
                .putExtra(CLIENT_ID_EXTRA, clientId)
                .putExtra(CLIENT_SECRET_EXTRA, clientSecret)
                .putExtra(REDIRECT_URI_EXTRA, redirectUri)
        }
    }
    
    private val webViewClient: WebViewClient = object : WebViewClient() {

        override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
            if (isAuthCodeExist(url)) {
                return false
            }
            return super.shouldOverrideUrlLoading(view, url)
        }

        @RequiresApi(Build.VERSION_CODES.N)
        override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                if (isAuthCodeExist(request.url.toString())) {
                    loadingDialog.startLoadingDialog()
                    getAccessToken(request.url.toString())
                    view.stopLoading()
                    return false
                }
                view.loadUrl(request.url.toString())
            }
            return false
        }
    }

    private inner class FlutterWebChromeClient : WebChromeClient() {
        override fun onCreateWindow(
            view: WebView, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message
        ): Boolean {
            val webViewClient: WebViewClient = object : WebViewClient() {
                @TargetApi(Build.VERSION_CODES.LOLLIPOP)
                override fun shouldOverrideUrlLoading(
                    view: WebView, request: WebResourceRequest
                ): Boolean {
                    if (isAuthCodeExist(request.url.toString())) {
                        return false
                    }
                    webView.loadUrl(request.url.toString())
                    return true
                }

                override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
                    if (isAuthCodeExist(url)) {
                        return false
                    }
                    webView.loadUrl(url)
                    return true
                }
            }
            val newWebView = WebView(webView.context)
            newWebView.webViewClient = webViewClient
            val transport = resultMsg.obj as WebView.WebViewTransport
            transport.webView = newWebView
            resultMsg.sendToTarget()
            return true
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_access_token)

        val intent = intent
        clientId = intent.getStringExtra(CLIENT_ID_EXTRA)!!
        clientSecret = intent.getStringExtra(CLIENT_SECRET_EXTRA)!!
        redirectUri = intent.getStringExtra(REDIRECT_URI_EXTRA)!!

        Log.d(
            "$TAG",
            "clientId = $clientId, clientSecret = $clientSecret, redirectUri = $redirectUri"
        )
        webView.loadUrl("https://www.instagram.com/oauth/authorize?client_id=$clientId&redirect_uri=$redirectUri&scope=user_profile,user_media&response_type=code")
        webView.settings.javaScriptEnabled = true

        // Open new urls inside the webview itself.
        webView.webViewClient = webViewClient

        // Multi windows is set with FlutterWebChromeClient by default to handle internal bug: b/159892679.
        webView.settings.setSupportMultipleWindows(true)
        webView.webChromeClient = FlutterWebChromeClient()
    }
    
    private fun isAuthCodeExist(url: String): Boolean {
        Log.d(TAG, "checkAuthCodeExist url = $url:")
        return url.startsWith(redirectUri)
    }
    
    private fun getAccessToken(url: String) {
        if (url.contains("code=")) {
            val startIndex = url.indexOf("code=", 0) + 5
            // #_ 是附加到重新导向 URI 的结尾,非代码本身的一部分
            val endIndex = url.lastIndex - 1
            val code = url.substring(startIndex, endIndex)
            Log.d(TAG, "oauth authorize code = $code")
            viewModel.getAssessToken(
                clientId,
                clientSecret,
                code,
                redirectUri
            )
        } else {
            Log.d(TAG, "redirect url error = $url")
            setResult(RESULT_CANCELED)
            finish()
        }
    }
}

<<:  [Day20] Flutter GetX routing

>>:  [Day26] swift & kotlin 游戏篇!(8) 小鸡BB-游戏制作-历史纪录

Day 04 : 以资料为中心的人工智慧 Data - Centric AI

垃圾进垃圾出「 Garbage in, garbage out 」,不去检视垃圾有多垃圾的情况下,...

Day 1. 前言

在决定铁人赛的题目前,我刚好有个前同事传讯息问我近况,顺便想套一下我当时的薪水,当时在公司大家对於薪...

21.unity简易对话介面设计概念

对话系统(dialogueSystem) 计画 小红帽想跟奶奶说话,然後把苹果送给奶奶。2D游戏经常...

Day3-丛集是在集什麽 何谓丛集(cluster)

何谓丛集 K8S的丛集指的就是,为了运行容器化的app,所使用的node机群,当你在运行k8s,你就...

Alpine Linux Porting (一)

没想到硬体的章节会因为限制结果直接炸裂XD 不过没关系,我们可以到时候拿到板子再回头写相关的事情。 ...