热点开启的一些尝试

测试机Android版本分别有14和15

1..采用LocalOnlyHotspot进行热点创建,热点存在的生命周期和应用进程一样。此热点开启只可连接通信,不可以使用互联网。

mWifiManager.startLocalOnlyHotspot

所需权限:@RequiresPermission(allOf = {CHANGE_WIFI_STATE, ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES},

此方法参数存在回调方法,可实现的分别是onstarted(热点创建成功,并且开启),onstopped(热点关闭),onfailed,(热点创建失败)。

通过此方法创建的热点,ssid和password都是随机的。ssid一般为Android开头

LocalOnlyHotspot存在两种开启:

1)

  这一种普通应用可以直接调用,传入对应的参数即可

mWifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
    @Override
    public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
      //需要创建全局对象,保持引用,不然存在几秒后开启就断开的情况。
        mLocalOnlyHotspotReservation = reservation;
    }

    @Override
    public void onStopped() {
        super.onStopped();
        Log.d("soft-ap-stop", "yes");
    }

    @Override
    public void onFailed(int reason) {
        super.onFailed(reason);
        Log.d("soft-ap-failure", "failure" + reason);
    }
}, new Handler(Looper.getMainLooper()));

2)这个存在config参数,意味着可以配置热点参数

此方法被标注了systemApi,通过反射调用成功了(下面有一些不需要反射哈,因为借助了ai,所以全部反射了),

// 获取 SoftApConfiguration 类
Class<?> softApConfigClass = Class.forName("android.net.wifi.SoftApConfiguration");

// 获取 Builder 类
Class<?> builderClass = Class.forName("android.net.wifi.SoftApConfiguration$Builder");

// 创建 Builder 实例
Constructor<?> builderConstructor = builderClass.getConstructor();
Object builder = builderConstructor.newInstance();

// 设置 SSID
Method setSsidMethod = builderClass.getMethod("setSsid", String.class);
setSsidMethod.invoke(builder, "testPot");

// 设置密码和安全类型 (WPA2_PSK)
Method setPassphraseMethod = builderClass.getMethod("setPassphrase", String.class, int.class);
int SECURITY_TYPE_WPA2_PSK = 1; // android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
setPassphraseMethod.invoke(builder, "123456789", SECURITY_TYPE_WPA2_PSK);

// 构建配置
Method buildMethod = builderClass.getMethod("build");
Object softApConfig = buildMethod.invoke(builder);

// 获取 LocalOnlyHotspotCallback 类
Class<?> callbackClass = Class.forName("android.net.wifi.WifiManager$LocalOnlyHotspotCallback");

// 创建回调实例
Object callback = new WifiManager.LocalOnlyHotspotCallback(){
    @Override
    public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
        mLocalOnlyHotspotReservation = reservation;
    }

    @Override
    public void onStopped() {
        super.onStopped();
        Log.d("soft-ap-stop", "yes");
    }

    @Override
    public void onFailed(int reason) {
        super.onFailed(reason);
        Log.d("soft-ap-failure", "yes" + reason);
    }
};

// 获取 Handler 类
Class<?> handlerClass = Class.forName("android.os.Handler");
Constructor<?> handlerConstructor = handlerClass.getConstructor();
Object handler = handlerConstructor.newInstance();

// 调用 startLocalOnlyHotspot 方法
Method startMethod = WifiManager.class.getMethod(
        "startLocalOnlyHotspot",
        softApConfigClass,
        Executor.class,
        callbackClass

);
startMethod.invoke(mWifiManager, softApConfig,  ContextCompat.getMainExecutor(this),callback );

2.ConnectivityManager的startTethering

参考:Android WiFi热点_app not allowed to read or update stored wifi ap c-CSDN博客

app的build.gradle里面添加依赖

implementation ("org.mockito:mockito-core:5.6.0")
implementation ("com.linkedin.dexmaker:dexmaker:2.28.3")
implementation ("com.linkedin.dexmaker:dexmaker-mockito:2.28.3")

权限

<uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions" />

代码:

File outputDir = getCodeCacheDir();
Class classOnStartTetheringCallback = Class.forName("android.net.ConnectivityManager$OnStartTetheringCallback");
Method startTethering = connectivityManager.getClass().getDeclaredMethod("startTethering", int.class, boolean.class, classOnStartTetheringCallback);
Object proxy = ProxyBuilder.forClass(classOnStartTetheringCallback).dexCache(outputDir).handler(new InvocationHandler() {
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        switch (method.getName()) {
            case "onTetheringStarted":
                Log.d("current-status", "onTetheringStarted");
                break;
            case "onTetheringFailed":
                Log.d("current-status", "onTetheringFailed");
                break;
            default:
                ProxyBuilder.callSuper(o, method, objects);
        }
        return null;
    }
}).build();

startTethering.invoke(connectivityManager, 0, false, proxy);

 尝试给其加上配置会出现:App not allowed to read or update stored WiFi AP config (uid = 10025)

3.其他的尝试也存在这个问题:

java.lang.SecurityException: App not allowed to read or update stored WiFi AP config (uid = 10025)

了解到可能是权限不足,不是系统级别,如果有人解决了,麻烦踢一下我,谢谢

其他的尝试(tetheringManager.startTethering)

  Class<?> tetheringManagerClass = Class.forName("android.net.TetheringManager");

                // 2. 获取 TetheringManager 实例
                Object tetheringManager = getSystemService("tethering");

                // 3. 获取 TetheringRequest 类及其 Builder 内部类
                Class<?> tetheringRequestClass = Class.forName("android.net.TetheringManager$TetheringRequest");
                Class<?> builderClass = Class.forName("android.net.TetheringManager$TetheringRequest$Builder");

                // 4. 创建 Builder 实例(假设网络类型为 WIFI=1)
                Constructor<?> builderConstructor = builderClass.getConstructor(int.class);
                Object builder = builderConstructor.newInstance(1); // TETHERING_WIFI=1

                // 5. 通过 Builder 设置参数(示例:豁免权限检查)
                Method setExemptMethod = builderClass.getMethod("setExemptFromEntitlementCheck", boolean.class);
                setExemptMethod.invoke(builder, true);


                // 6. 构建 TetheringRequest 实例
                Method buildMethod = builderClass.getMethod("build");
                Object tetheringRequest = buildMethod.invoke(builder);

                Class<?> callbackClass = Class.forName("android.net.TetheringManager$StartTetheringCallback");

//          
                // 使用 ProxyBuilder 创建代理对象
                InvocationHandler handler = new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        switch (method.getName()) {
                            case "onTetheringStarted":
                                Log.d("TAG", "热点已启动");
                                break;
                            case "onTetheringFailed":
                                Log.e("TAG", "启动失败,错误码: " + args[0]);
                                break;
                            default:
                                break;
                        }
                        return null; // 对于接口方法,通常返回 null 或适当的默认值
                    }
                };

                File outputDir = getCodeCacheDir();
                Object proxy = ProxyBuilder.forClass(Object.class) // 使用 Object 类作为基类
                        .dexCache(outputDir)
                        .implementing(callbackClass) // 显式声明实现的接口
                        .handler(handler)
                        .build();


                // 8. 获取 startTethering 方法并调用
                Method startTetheringMethod = tetheringManagerClass.getDeclaredMethod(
                        "startTethering",
                        tetheringRequestClass,
                        Executor.class,
                        callbackClass
                );
                startTetheringMethod.setAccessible(true);

                // 9. 执行调用
                startTetheringMethod.invoke(
                        tetheringManager,
                        tetheringRequest,
                        ContextCompat.getMainExecutor(this),
                        proxy
                );

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值