Ionic Vue安卓项目中如何将Java回调的Code传递至Vue组件
Ionic Vue安卓应用:将iNaturalist认证Code从CallbackActivity传递到Vue组件
我用Ionic+Vue开发安卓应用,基于iNaturalist做OAuth2认证。用户完成认证后,回调URLmyapp://callback会带回code参数,已经在Java的CallbackActivity里拦截到这个code,但不知道怎么把它传给Vue组件。核心需求是实现Java端发送事件,Vue端监听并接收code。
实现步骤
一、Java端:通过Capacitor Bridge发送事件到Vue
Ionic默认集成Capacitor,我们可以利用Capacitor的Bridge直接向Vue的window对象发送自定义事件,不需要额外跳转MainActivity(如果需要弹窗确认可以保留弹窗逻辑)。
修改CallbackActivity.java
import com.getcapacitor.Bridge; import com.getcapacitor.BridgeActivity; import com.getcapacitor.JSObject; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.app.AlertDialog; import android.content.DialogInterface; public class CallbackActivity extends BridgeActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); Uri data = intent.getData(); if (data != null && "myapp".equals(data.getScheme()) && "callback".equals(data.getHost())) { String codeParam = data.getQueryParameter("code"); if (codeParam != null) { // 需要弹窗确认就调用这个方法;不需要的话直接调用sendAuthCodeToVue displayReceivedCode(codeParam); } else { finish(); } } } private void displayReceivedCode(String codeParam) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Received Code"); builder.setMessage("The code received is: " + codeParam); builder.setPositiveButton("OK", (dialog, which) -> { dialog.dismiss(); sendAuthCodeToVue(codeParam); }); AlertDialog alertDialog = builder.create(); alertDialog.show(); } private void sendAuthCodeToVue(String code) { Bridge bridge = getBridge(); if (bridge != null) { JSObject eventData = new JSObject(); eventData.put("code", code); // 触发window上的自定义事件,事件名前后端要一致 bridge.triggerWindowJSEvent("authCodeReceived", eventData); } // 发送完事件关闭当前Activity finish(); } }
二、Vue端:监听自定义事件并处理code
在Login.vue组件中,挂载时监听Java发送的authCodeReceived事件,拿到code后调用接口换取token。
修改Login.vue
<template> <!-- 你的登录页面内容 --> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue'; import { useStore } from 'vuex'; import { Browser } from '@capacitor/browser'; const store = useStore(); let authCodeEventListener = null; // 组件挂载时添加事件监听 onMounted(() => { authCodeEventListener = (event) => { const authCode = event.detail.code; if (authCode) { // 拿到code后立刻去换token exchangeCodeForToken(authCode); } }; window.addEventListener('authCodeReceived', authCodeEventListener); }); // 组件销毁时移除监听,避免内存泄漏 onUnmounted(() => { if (authCodeEventListener) { window.removeEventListener('authCodeReceived', authCodeEventListener); } }); async function login({ commit }) { const clientId = 'xxxxxxxxxxxxxxxxxx'; const redirectUri = 'myapp://callback'; let authorizationUrl = 'https://www.inaturalist.org/oauth/authorize'; const responseType = 'code'; const codeChallengeMethod = 'S256'; commit('SET_LOADING', "Logging in..."); const codeVerifier = generateCodeVerifier(); const codeChallenge = await generateCodeChallenge(codeVerifier); commit('SET_CODE_VERIFIER', codeVerifier); // 拼接完整授权URL authorizationUrl += `?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=${responseType}&code_challenge=${codeChallenge}&code_challenge_method=${codeChallengeMethod}`; // 打开浏览器授权页面 await Browser.open({ url: authorizationUrl }); } // 用code换token的逻辑 async function exchangeCodeForToken(code) { const codeVerifier = store.state.codeVerifier; const clientId = 'xxxxxxxxxxxxxxxxxx'; const redirectUri = 'myapp://callback'; try { const response = await fetch('https://www.inaturalist.org/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ client_id: clientId, redirect_uri: redirectUri, grant_type: 'authorization_code', code: code, code_verifier: codeVerifier }) }); const tokenData = await response.json(); // 把token存入Vuex或者本地存储 store.commit('SET_AUTH_TOKEN', tokenData.access_token); // 登录成功后的操作,比如跳转到首页 } catch (error) { console.error('获取访问令牌失败:', error); // 处理错误,比如提示用户 } } // 保留你的codeVerifier和challenge生成方法 function generateCodeVerifier() { // 你的现有实现 } async function generateCodeChallenge(codeVerifier) { // 你的现有实现 } </script>
关键注意点
- CallbackActivity继承BridgeActivity:这样才能直接获取Capacitor的Bridge实例,实现事件发送。
- 事件名称一致:Java端的
authCodeReceived和Vue端监听的事件名必须完全相同。 - 移除事件监听:组件销毁时一定要移除监听,防止内存泄漏。
内容的提问来源于stack exchange,提问作者rohitmg
相关产品推荐
相关产品推荐

