1. 监听wifi相关的Broadcast
1.1 根据布局找到wifi显示用到的方法
- 首先研究原生carSetting的代码布局---找到wifi_list_fragment.xml,可以知道这里是wifi显示界面的xml
- 然后是找到wifi对应的布局部分:
<com.android.car.ui.preference.CarUiPreferenceandroid:key="@string/pk_wifi_status"settings:controller="com.android.car.settings.wifi.WifiStatusPreferenceController"settings:showChevron="false"/><com.android.car.settings.common.LogicalPreferenceGroupandroid:key="@string/pk_wifi_list"settings:controller="com.android.car.settings.wifi.WifiEntryListPreferenceController"/><com.android.car.ui.preference.CarUiPreferenceandroid:fragment="com.android.car.settings.wifi.AddWifiFragment"android:icon="@drawable/ic_add"android:key="@string/pk_add_wifi"android:title="@string/wifi_setup_add_network"settings:controller="com.android.car.settings.wifi.AddWifiPreferenceController"settings:showChevron="false"/>
不需要明白这个Preference是干嘛的,只需要了解:
WifiStatusPreferenceController用来拿wifi状态
WifiEntryListPreferenceController用来拿wifi相关信息
AddWifiPreferenceController用来添加更多的wifi相关信息
-
1.2 WifiEntryListPreferenceController
在WifiEntryListPreferenceController.java中 updateState函数拿到了wifi项,获取了已连接和未连接的wifi项。
@Overrideprotected void updateState(PreferenceGroup preferenceGroup) {if (getCarWifiManager() == null) {return;}mWifiEntries = fetchWifiEntries(); // 获取所有的wifi项LOG.d("showing wifiEntries: " + mWifiEntries.size());preferenceGroup.setVisible(!mWifiEntries.isEmpty());preferenceGroup.removeAll();WifiEntry connectedWifiEntry = getCarWifiManager().getConnectedWifiEntry(); // 获取已连接的wifi项for (WifiEntry wifiEntry : mWifiEntries) {if (wifiEntry.equals(connectedWifiEntry)) {preferenceGroup.addPreference(createWifiEntryPreference(wifiEntry, /* connected= */ true));} else {preferenceGroup.addPreference(createWifiEntryPreference(wifiEntry, /* connected= */ false));}}}
其中关键的就是getCarWifiManager();
于是研究CarWifiManger的构造函数,即WifiBasePreferenceController.java其中的new CarWifiManager
-
1.3 CarWifiManger的构造函数
收
public CarWifiManager(Context context, Lifecycle lifecycle) {mContext = context;mLifecycle = lifecycle;mLifecycle.addObserver(this);mWifiManager = mContext.getSystemService(WifiManager.class);mWorkerThread = new HandlerThread(TAG+ "{" + Integer.toHexString(System.identityHashCode(this)) + "}",android.os.Process.THREAD_PRIORITY_BACKGROUND);mWorkerThread.start();mWifiTracker = WifiUtil.createWifiPickerTracker(lifecycle, context,new Handler(Looper.getMainLooper()), mWorkerThread.getThreadHandler(),/* listener= */ this);}
其中的关键就是WifiUtil的createWifiPickerTracker函数,
-
1.4 createWifiPickerTracker
在WifiUtil.java中的createWifiPickerTracker传入了几个参数:
mWifiTracker = WifiUtil.createWifiPickerTracker(lifecycle, context,new Handler(Looper.getMainLooper()), mWorkerThread.getThreadHandler(),/* listener= */ this);
1)mainHandler--即new Handler(Looper.getMainLooper()); 这个是主线程的UI handler
2)而mWorkHandler--用来处理非UI事件
3) listener则是调用WifiPickerTracker.WifiPickerTrackerCallback这个回调的地方,可以看到CarWifiManager.java中的onWifiStateChanged是实现WifiPickerTrackerCallback的回调。
-
1.5 wifiPickerTracker的构造
public static WifiPickerTracker createWifiPickerTracker(Lifecycle lifecycle, Context context,Handler mainHandler, Handler workerHandler,long maxScanAgeMillis, long scanIntervalMillis,WifiPickerTracker.WifiPickerTrackerCallback listener) {return new WifiPickerTracker(lifecycle, context,context.getSystemService(WifiManager.class),context.getSystemService(ConnectivityManager.class),context.getSystemService(NetworkScoreManager.class),mainHandler, workerHandler, ELAPSED_REALTIME_CLOCK,maxScanAgeMillis, scanIntervalMillis,listener);}
WifiPickerTracker.java 在 frameworks/opt/net/wifi/libs/WifiTrackerlib/src目录下。
而 class WifiPickerTracker extends BaseWifiTracker, 翻看BaseWifiTracker
-
1.6 BaseWifiTracker.java的功能
-
1.6.1 BaseWifiTracker.java的onStart和onStop
以下是个人觉得比较重要的点:
1) onStart 和 onStop, 其中onStart在收到 Lifecycle.Event.ON_STAR会调用。而onStop收到Lifecycle.Event.ON_STOP会调用。
- 那么这个lifecycle是指的什么呢? 在BaseWifiTracker的构造函数中:调用了lifecycle.addObserver(this);
- 看下调用栈, 从CarWifiManager的构造函数---->createWifiPickerTracker---->wifiPickerTracker的构造---> BaseWifiTracker的构造。
lifeCycle是从CarWifiManager的构造函数传过来的、而CarWifiManger的构造函数也调用了mLifecycle.addObserver(this); 这个界面也实现了onStart回调来监听Lifecycle.Event.ON_START。
- 那么onStart则是先调用到CarWifiManager类,在调用到BaseWifiTracker类。
2)BaseWifiTracker的onStart监听了wifi相关的BroadCast, 而在onStop取消了监听wifi相关的BroadCast
(所以当出现不能收到wifi相关的BroadCast后,考虑是不是调用到了onStop, 之后未调用到onStart. )
-
1.6.2 BaseWifiTracker.java的监听wifi相关功能
监听wifi相关的BroadCast信号,然后收到了BroadCast之后进入实现的BroadcastReceiver, 这里会调用到handle....的回调方法,以handleNetworkStateChangedAction为例。
- handleNetworkStateChangedAction
WifiPickerTracker继承了BaseWifiTracker,WifiPickerTracker.java实现了接口handleNetworkStateChangedAction,最后调用了updateWifiEntries()接口来更新扫描到的Wifi设备。
-
1.6.3 wifi的连接状态、扫描结果,信号变化的信号监听
1.7.总结:
总的来说:0)createWifiPickerTracker创建WifiPickerTracker对象,传入lifeCycle变量。
1)BaseWifiTracker在根据传入的lifeCycle,在收到onStart事件后,开始监听wifi相关的信号。
2)然后调用继承BaseWifiTracker的子类WifiPickerTracker来更新wifi相关结果
3)WifiPickerTracker提供接口供app使用--比如fetchEntries(); 拿到扫描到的wifi
2.wifi的连接,断开,忽略操作:
2.1 调用入口
调用的是WifiEntryListPreferenceController.java的createWifiEntryPreference方法
wifiEntry.connect(new WifiEntryConnectCallback(wifiEntry, /* editIfNoConfig= */ true));
查看wifiEntry.java的connect方法:
public void connect(@Nullable ConnectCallback callback) {
// Do nothing.
}
那么这个wifiEntry应该就是指的是继承wifiEntry的对象实现的connect方法。
2.2 查看connect方法的调用栈:
- updateState: connect方法是在updateState()中调用的,是从fetchWifiEntries();中拿到的对象。
- fetchWifiEntries: 调用的是 WifiEntry connectedWifiEntry=getCarWifiManager().getConnectedWifiEntry();
- 即CarWifiManager.java的getConnectedWifiEntry方法中的mWifiTracker.getConnectedWifiEntry();
- 即WifiPickerTracker.getConnectedWifiEntry方法。
- 而getConnectedWifiEntry指定的对象是updateWifiEntries()中更新的mWifiEntries。
从而可以发现,mWifiEntries存入的对象是StandardWifiEntry,PasspointWifiEntry,OsuWifiEntry。。。本文以最常用的StandardWifiEntry为切入点。那么wifiEntry.connect应该是调用到StandardWifiEntry.connect方法,在StandardWifiEntry类中可以找打如下的方法。
2.3 StandardWifiEntry.java
- 连接调用
mWifiManager.connect(mTargetWifiConfig.networkId, new ConnectActionListener());
ConnectActionListener是在WifiEntry.java中实现的,处理连接成功,失败的事件
-
断开连接
mWifiManager.disconnect();
-
忽略连接
mWifiManager.forget(mTargetWifiConfig.networkId, new ForgetActionListener());
ForgetActionListener是在WifiEntry.java中实现的,处理连接成功,失败的事件