Android WebView中通过JS获取PHP的FCM Token返回null的解决方案
解决方案
问题根源
你遇到的getActiveToken()返回null的核心原因是:你在MainFragment中新建了一个独立的JavaScriptAPI实例,而WebView中注入的是另一个未被你引用的实例。JS代码调用的是WebView绑定的实例的userToken()方法,但你调用getActiveToken()的是全新的实例,自然拿不到值。
修复步骤
1. 统一JavaScriptAPI实例并添加回调机制
修改JavaScriptAPI类,新增回调接口,确保Token接收时能通知到MainFragment:
public class JavaScriptAPI { private Activity mActivity; private volatile String activeToken; private OnTokenReceivedListener tokenListener; // 定义回调接口 public interface OnTokenReceivedListener { void onTokenReceived(String token); } // 构造方法传入回调 public JavaScriptAPI(Activity activity, OnTokenReceivedListener listener) { mActivity = activity; this.tokenListener = listener; } @JavascriptInterface public void userToken(String token){ activeToken = token; Log.d("JavaScriptAPI", "Received Token: " + activeToken); // 切换到主线程通知Fragment(JS接口调用在WebView后台线程) if (tokenListener != null) { mActivity.runOnUiThread(() -> tokenListener.onTokenReceived(token)); } } public String getActiveToken() { return activeToken; } }
2. 在MainFragment中绑定统一实例并实现回调
在MainFragment中创建唯一的JavaScriptAPI实例,注入WebView,并实现回调来处理Token对比和Volley请求:
public class MainFragment extends Fragment implements JavaScriptAPI.OnTokenReceivedListener { private WebView webView; private JavaScriptAPI javaScriptAPI; private String fcmToken; // 已获取的FCM Token @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_main, container, false); webView = view.findViewById(R.id.webview); // 启用JavaScript WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); // 创建唯一的JavaScriptAPI实例并绑定回调 javaScriptAPI = new JavaScriptAPI(getActivity(), this); webView.addJavascriptInterface(javaScriptAPI, "MyApp"); // 获取FCM Token(替换为你的实际获取逻辑) FirebaseMessaging.getInstance().getToken() .addOnCompleteListener(task -> { if (task.isSuccessful()) { fcmToken = task.getResult(); } }); // 加载PHP页面 webView.loadUrl("你的PHP页面URL"); webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // 无需在此处调用getActiveToken,等待回调即可 } }); return view; } // 实现回调方法,处理Token对比与请求 @Override public void onTokenReceived(String phpToken) { if (fcmToken == null) { Log.d("MainFragment", "FCM Token未获取完成,延迟处理"); return; } // 对比Token,决定是否发起Volley请求 if (!fcmToken.equals(phpToken)) { sendTokenToServer(fcmToken); } else { Log.d("MainFragment", "Token一致,无需更新"); } } // Volley请求逻辑 private void sendTokenToServer(String token) { String url = "你的Token更新接口URL"; StringRequest stringRequest = new StringRequest(Request.Method.POST, url, response -> Log.d("Volley", "Token更新成功"), error -> Log.e("Volley", "Token更新失败", error)) { @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<>(); params.put("token", token); return params; } }; Volley.newRequestQueue(getActivity()).add(stringRequest); } }
关键注意事项
- 确保WebView已启用JavaScript:
webSettings.setJavaScriptEnabled(true) - JS代码中的
MyApp必须与WebView注入的接口名称完全一致 - JS接口方法运行在WebView的后台线程,通知主线程时需调用
runOnUiThread - 不要在
onPageFinished中直接调用getActiveToken,因为JS代码可能尚未执行完成,回调机制更可靠
内容的提问来源于stack exchange,提问作者Super Coder
相关产品推荐
相关产品推荐

