You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Frida JS执行HTTP请求遇NetworkOnMainThreadException问题求助

解决Frida Hook中Android网络请求的主线程限制问题

核心原因

你遇到的android.os.NetworkOnMainThreadException是因为Android系统禁止主线程执行网络IO操作,而你Hook的com.ex.MediaPlayMgr.play方法刚好运行在主线程中,直接在Hook代码里发起HTTP请求就会触发这个异常。

解决方案:后台线程同步执行网络请求

要在Frida JS中安全获取自定义InputStream,需要把网络请求放到后台线程执行,同时通过同步机制等待请求完成,再替换原方法的参数。以下是可行的代码示例:

示例代码(使用Java线程+CountDownLatch同步)

Java.perform(() => {
    const MediaPlayMgr = Java.use('com.ex.MediaPlayMgr');
    const CountDownLatch = Java.use('java.util.concurrent.CountDownLatch');
    const OkHttpClient = Java.use('okhttp3.OkHttpClient');
    const Request = Java.use('okhttp3.Request');
    const ResponseBody = Java.use('okhttp3.ResponseBody');

    MediaPlayMgr.play.overload('java.io.InputStream', 'java.lang.String').implementation = function(inputStream, str) {
        console.log('进入play方法');
        let customInputStream = null;
        const latch = CountDownLatch.$new(1);

        // 启动后台线程执行网络请求
        const thread = Java.use('java.lang.Thread').$new({
            run: function() {
                try {
                    console.log('step3: 开始执行网络请求');
                    // 构建OkHttp请求
                    const client = OkHttpClient.$new();
                    const request = Request.Builder.$new().url('你的目标URL').build();
                    const response = client.newCall(request).execute();
                    
                    if (response.isSuccessful()) {
                        customInputStream = response.body().byteStream();
                        console.log('step4: 网络请求完成,获取到输入流');
                    }
                } catch (e) {
                    console.error('网络请求出错:', e.message);
                    // 异常时 fallback 到原输入流
                    customInputStream = inputStream;
                } finally {
                    latch.countDown(); // 通知主线程请求完成
                }
            }
        });
        thread.start();
        
        // 等待后台线程完成
        latch.await();

        // 替换输入流,调用原方法
        return this.play(customInputStream, str);
    };
});

关键注意点

  • 使用CountDownLatch实现主线程和后台线程的同步,确保在获取到自定义流之后再执行原方法逻辑。
  • 异常处理要做好,避免因为网络请求失败导致原方法无法执行,可在异常时 fallback 到原输入流。
  • 如果你用java.net.HttpURLConnection,替换线程内的网络请求代码即可,逻辑是一样的:
    // HttpURLConnection 版本的网络请求代码
    const URL = Java.use('java.net.URL');
    const HttpURLConnection = Java.use('java.net.HttpURLConnection');
    const url = URL.$new('你的目标URL');
    const conn = url.openConnection();
    conn.setRequestMethod('GET');
    customInputStream = conn.getInputStream();
    
  • 确保目标应用已经申请了android.permission.INTERNET权限,否则会出现权限错误。

额外提示

如果Hook的方法本身是异步执行的,也可以考虑用Android的Handler将网络请求抛到后台HandlerThread,但上述同步等待的方式更通用,能保证替换流的逻辑和原方法执行顺序一致。

内容的提问来源于stack exchange,提问作者kenshin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 06:40:59