Android之解决开启热点后跳转页面不稳定问题

1 问题

在Android8.0版本以后,开启热点我们采用的下面这种方式,但是跳转页面后热点会断开,手机不能互相传文件了

权限说明:Android8.0需要位置权限和GPS权限,同时手机热点还不能是开启状态。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            try {
                mWifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
                    @Override
                    public void onFailed(int reason) {
                        super.onFailed(reason);
                        Log.i(TAG, "onFailed start");
                    }

                    @Override
                    public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
                        super.onStarted(reservation);
                        Log.i(TAG, "onStarted start");
                        mReservation = reservation;
                        WifiConfiguration wifiConfiguration = reservation.getWifiConfiguration();
                        String ssid = wifiConfiguration.SSID;
                        String pwd = wifiConfiguration.preSharedKey;
                        Log.i(TAG, "ssid is:" + ssid);
                        Log.i(TAG, "pwd is:" + pwd);
                    }

                    @Override
                    public void onStopped() {
                        super.onStopped();
                        sendBroadcast(STOP_STATE, "", "");
                    }
                }, new Handler());
            } catch (Exception e) {
                e.printStackTrace();
                Log.e(TAG, "startLocalOnlyHotspot error");
            }
    }

 

 

 

 

2 思考

1)全局静态保存mReservation变量,跳页面的时候不执行close方法。

我们看到上面的代码

mReservation = reservation;

我们关闭,是这样关闭的

 if (mReservation != null) {
     mReservation.close();
     mReservation = null;
 }

为了防止热点关闭,我们一开始对mReservation变量做了全局静态的保存,但是依然存在开启热点后,热点会断的问题。

2)反编译"茄子快传"代码,分析别人的产品

"茄子快传" 这个app也是热点生成后多个手机连接,然后进行文件的发送,我们反编译“茄子快传”代码

搜索关键字startLocalOnlyHotspot,如下图

这里看起来像用了反射,我们点击进去看这个函数

 

的确用了反射,明明有API为啥用反射呢?现在也搞不懂,到底有没有蹊跷现在也不知,然后我再看下在哪里调用这个函数

很明显这里开启了一个服务,然后在onStartCommand函数里面传递了一个携带参数的intent过来,如果是0就是执行关闭函数,如果是1的话就执行开启热点函数,然后它也重写了这个回调LocalOnlyHotspotCallback

 把LOHSService作为构造函数参数传递进去,然后开启热点成功后,执行this.a.a(1, str, wifiConfiguration.preSharedKey);
这个函数,也就是发送携带用户名和密码的广播到其它页面

然后我也这样模仿开启一个服务,在服务里面开启热点去测试,配置如下

        <service android:name="**********.LocalHotService" android:exported="false">
            <intent-filter>
                <action android:name="**********.LocalHotService"/>
            </intent-filter>
        </service>

发现依然不稳定,只不过我开启的时候是用API来开启的,不是用的反射,然后我就采用它的代码,用反射进行开启,效果依然不稳定,说明这里没区别,由于第一次开启热点,非常稳定,第二次开启热点会很不稳定,所以思考是不是由于关闭热点出了问题

 if (mReservation != null) {
     mReservation.close();
     mReservation = null;
 }

然后我尝试,不采用中间变量mReservation保存,用反射进行关闭

    @TargetApi(Build.VERSION_CODES.M)
    public void stopHotPoint(Context context) {
        try {
            ConnectivityManager manager = (ConnectivityManager) context.getApplicationContext().getSystemService(ConnectivityManager.class);
            Method method = manager.getClass().getDeclaredMethod("stopTethering", int.class);
            if (method == null) {

            } else {
                method.invoke(manager, 0);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }
    }

这样掉,还需要申请一个修改系统设置的权限,需要通过startActivity去申请,当然

android.permission.WRITE_SETTINGS

当然在AndroidManifest.xml里面也要配置好

    <uses-permission
        android:name="android.permission.WRITE_SETTINGS"

        tools:ignore="ProtectedPermissions" />

 这样程序才不会奔溃

然后我们再分析下源码,这里系统会调用finalize方法,内存不够就可能执行,然后里面回调用close方法,然后close里面会调用stopLocalOnlyHotspot()方法,这里就会关闭热点
可能由于内存不够导致不稳定,然后既然开启了热点服务,我们为什么不能在开辟一个进程呢?
然后把服务放在另外一个进程里面,另外一个进程没有太多其它操作,内存一般不会执行Java垃圾回收

然后在单独一个进程开启服务,测试这个热点就非常稳定了,问题也解决了

3 解决办法

再开辟一个新的进程里面开启热点服务

  <service android:name="*****.LocalHotService" android:exported="false"
            android:process=":aptest">
            <intent-filter>
                <action android:name="*****.LocalHotService"/>
            </intent-filter>
        </service>

 

猜你喜欢

转载自blog.csdn.net/u011068702/article/details/106724165