Android开发:如何实现WebView内输入打字时播放自定义音效
Android WebView输入打字触发自定义音效实现方案
代码优化及修改说明
你原有代码存在两个可优化问题:
- 每次调用
soundOn()都重新创建SoundPool实例,会导致内存占用高、音效播放延迟,建议改为全局初始化一次 - 变量名大小写错误:
webSettings定义后使用时写成了小写开头的websettings
具体实现思路
通过注入JavaScript监听网页内所有输入框的按键事件,触发Android原生的音效播放逻辑,不需要修改网页源码,同时采用事件委托适配所有动态生成的输入元素。
完整修改后代码
public class WebViewActivity extends AppCompatActivity { private WebView webView; private SoundPool soundPool; private int soundId; String url = "www.google.com"; // JS桥接接口类,供网页侧调用原生方法 public class JsSoundInterface { @JavascriptInterface public void playTypeSound() { runOnUiThread(() -> soundOn()); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.webview); // 提前初始化音效池,避免重复创建 initSoundPool(); webView = findViewById(R.id.webView); WebSettings webSettings = webView.getSettings(); webSettings.setDomStorageEnabled(true); webSettings.setJavaScriptEnabled(true); webView.getSettings().setAppCachePath(getApplicationContext().getFilesDir().getAbsolutePath() + "/cache"); webView.getSettings().setDatabasePath(getApplicationContext().getFilesDir().getAbsolutePath() + "/databases"); // 绑定JS桥接接口 webView.addJavascriptInterface(new JsSoundInterface(), "AndroidSoundBridge"); if (Build.VERSION.SDK_INT >= 21) { CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true); } else { CookieManager.getInstance().setAcceptCookie(true); } webView.loadUrl(url); webView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { soundOn(); view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // 注入全局按键监听JS,事件委托适配所有动态输入元素 String injectJs = "javascript:(function() {" + "document.addEventListener('keydown', function(e) {" + " var target = e.target;" + " if(target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {" + " window.AndroidSoundBridge.playTypeSound();" + " }" + "});" + "})()"; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { webView.evaluateJavascript(injectJs, null); } else { webView.loadUrl(injectJs); } } }); } private void initSoundPool() { soundPool = new SoundPool.Builder() .setMaxStreams(5) .build(); // 预加载音效资源 soundId = soundPool.load(getApplicationContext(), R.raw.mysound, 1); } private void soundOn() { // 直接播放预加载的音效,无需重复加载 soundPool.play(soundId, 1f, 1f, 0, 0, 1); } @Override protected void onDestroy() { super.onDestroy(); // 释放音效池资源 if(soundPool != null) { soundPool.release(); soundPool = null; } } }
内容的提问来源于stack exchange,提问作者Gedanggoreng
相关产品推荐
相关产品推荐

