一.Wife的基础知识

WIFI就是一种无线联网技术,常见的是使用无线路由器。那么在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网。如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为“热点”。
      在Android中对Wifi操作,android本身提供了一些有用的包,在android.net.wifi包下面。主要包括以下几个类和接口:

(一)ScanResult

主要用来描述已经检测出的接入点,包括接入点的地址,接入点的名称,身份认证,频率,信号强度等信息。

(二)WifiConfiguration

Wifi网络的配置,包括安全设置等。

(三)WifiInfo

wifi无线连接的描述,包括接入点,网络连接状态,隐藏的接入点,IP地址,连接速度,MAC地址,网络ID,信号强度等信息。这里简单介绍一下这里的方法:

1. getBSSID() 获取BSSID

2. getDetailedStateOf() 获取客户端的连通性

3. getHiddenSSID() 获得SSID 是否被隐藏

4. getIpAddress() 获取IP 地址

5. getLinkSpeed() 获得连接的速度

6. getMacAddress() 获得Mac 地址

7. getRssi() 获得802.11n 网络的信号

8. getSSID() 获得SSID

9. getSupplicanState() 返回具体客户端状态的信息

(四)WifiManager

管理我们的wifi 连接,这里已经定义好了一些类,可以供我们使用。

(五)获取WIFI网卡的状态

WIFI网卡的状态是由一系列的整形常量来表示的。
1. WIFI_STATE_DISABLED : WIFI网卡不可用(1)
2. WIFI_STATE_DISABLING : WIFI网卡正在关闭(0)
3. WIFI_STATE_ENABLED : WIFI网卡可用(3)
4. WIFI_STATE_ENABLING : WIFI网正在打开(2) (WIFI启动需要一段时间)
5. WIFI_STATE_UNKNOWN : 未知网卡状态

(六)Wifi权限,无非是网络和Wife

<uses-permission
android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

(七)常用方法

1.开启WIFI

 public void WifiOpen(){if(!localWifiManager.isWifiEnabled()){localWifiManager.setWifiEnabled(true);}}

2.扫描WIFI信号

public void WifiStartScan(){localWifiManager.startScan();}

3、得到扫描WIFI结果

public List<ScanResult> getScanResults(){return localWifiManager.getScanResults();//得到扫描结果}

4.得到WIFi的配置好的信息,包含配置好的密码

 //得到Wifi配置好的信息public void getConfiguration(){wifiConfigList = localWifiManager.getConfiguredNetworks();//得到配置好的网络信息for(int i =0;i<wifiConfigList.size();i++){                     Log.i("getConfiguration",wifiConfigList.get(i).SSID); Log.i("getConfiguration",String.valueOf(wifiConfigList.get(i).networkId));}}

5、根据WIFI的名称SSID判定指定WIFI是否已经配置好,配置好则返回其networkId,用于连接。之前尝试了BSSID地址没成功,所以只能使用SSID

//判定指定WIFI是否已经配置好,依据WIFI的地址BSSID,返回NetIdpublic int IsConfiguration(String SSID){Log.i("IsConfiguration",String.valueOf(wifiConfigList.size()));for(int i = 0; i < wifiConfigList.size(); i++){Log.i(wifiConfigList.get(i).SSID,String.valueOf( wifiConfigList.get(i).networkId));if(wifiConfigList.get(i).SSID.equals(SSID)){//地址相同return wifiConfigList.get(i).networkId;}}return -1;}

6、如果需要连接的WIFI没有配置好,即没有保存密码。则为指定名称ssid的WIFI添加密码信息psw,添加成功后返回给其分配的networId,同于连接

 //添加指定WIFI的配置信息,原列表不存在此SSIDpublic int AddWifiConfig(List<ScanResult> wifiList,String ssid,Stringpwd){int wifiId = -1;for(int i = 0;i < wifiList.size(); i++){ScanResult wifi = wifiList.get(i);if(wifi.SSID.equals(ssid)){Log.i("AddWifiConfig","equals");WifiConfiguration wifiCong = new WifiConfiguration();wifiCong.SSID = "\""+wifi.SSID+"\"";//\"转义字符,代表"wifiCong.preSharedKey = "\""+pwd+"\"";//WPA-PSK密码wifiCong.hiddenSSID = false;wifiCong.status = WifiConfiguration.Status.ENABLED;wifiId = localWifiManager.addNetwork(wifiCong);//将配置好的特
定WIFI密码信息添加,添加完成后默认是不激活状态,成功返回ID,否则为-1if(wifiId != -1){return wifiId;}}}return wifiId;}

7、根据步骤6配置好需要连接的WIFI密码信息后,下面通过networkId连接指定WIFI。在连接经过步骤6刚添加配置信息的WIFI信号之前需要重新执行下步骤4,得到新的配置好信息的列表。

//连接指定Id的WIFIpublic boolean ConnectWifi(int wifiId){for(int i = 0; i < wifiConfigList.size(); i++){WifiConfiguration wifi = wifiConfigList.get(i);if(wifi.networkId == wifiId){while(!(localWifiManager.enableNetwork(wifiId, true))){//激活该Id,建立连接//status:0--已经连接,1--不可连接,2--可以连接Log.i("ConnectWifi",String.valueOf(wifiConfigList.get(wifiId).status));}return true;}}return false;}

二.Wife的开发示例程序

这个程序运行后可以扫描周边的Wife,并且做连接,还有历史记录。
      程序运行后的界面:

可以点击对应的按钮,显示周边的Wife信息,和连接的Wife历史记录。点击某个Wife条目,就是连接的操作,输入正确的密码就可以完成Wife的连接。
下面是程序的代码:

(一)添加权限

<!--设计Wife示例使用的权限,网络权限和wife权限-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

(二)布局文件设计

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="open"android:text="打开wifi" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="close"android:text="关闭wifi" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="scan"android:text="扫描wifi" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="getGood"android:text="获取连接过的wifi配置信息" /><ListView
        android:id="@+id/lv"android:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>

(三)设计一个WifeUtil工具类

package fuxi.wifedemo;import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;import java.util.List;/*** wife使用的工具类*/
public class WifiUtil {// WifiManager.WIFI_STATE_ENABLED WiFi已打开// WifiManager.WIFI_STATE_ENABLING WiFi打开中// WifiManager.WIFI_STATE_DISABLING WiFi关闭中// WifiManager.WIFI_STATE_DISABLED WiFi已关闭// WifiManager.WIFI_STATE_UNKNOWN 未知的WiFi状态// 定义一个WifiManager对象private WifiManager mWifiManager;// 定义一个WifiInfo对象private WifiInfo mWifiInfo;// 扫描出的网络连接列表private List<ScanResult> mWifiList;// 网络连接列表private List<WifiConfiguration> mWifiConfigurations;WifiLock mWifiLock;Context mContext;//传入上下文public WifiUtil(Context context) {// 取得WifiManager对象mContext = context;mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);// 取得WifiInfo对象mWifiInfo = mWifiManager.getConnectionInfo();}// 打开wifipublic void openWifi() {if (!mWifiManager.isWifiEnabled()) {mWifiManager.setWifiEnabled(true);}}//判断wife是否是连接状态public boolean isConn() {ConnectivityManager connManager = (ConnectivityManager) mContext.getSystemService(mContext.CONNECTIVITY_SERVICE);NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);return mWifi.isConnected();}// 关闭wifipublic void closeWifi() {if (mWifiManager.isWifiEnabled()) {mWifiManager.setWifiEnabled(false);}}// 检查当前wifi状态public int checkState() {return mWifiManager.getWifiState();}// 锁定wifiLockpublic void acquireWifiLock() {mWifiLock.acquire();}// 解锁wifiLockpublic void releaseWifiLock() {// 判断是否锁定if (mWifiLock.isHeld()) {mWifiLock.acquire();}}// 创建一个wifiLockpublic void createWifiLock() {mWifiLock = mWifiManager.createWifiLock("test");}// 得到配置好的网络public List<WifiConfiguration> getConfiguration() {return mWifiConfigurations;}// 指定配置好的网络进行连接public boolean connetionConfiguration(int index) {if (index > mWifiConfigurations.size()) {return false;}// 连接配置好指定ID的网络return mWifiManager.enableNetwork(mWifiConfigurations.get(index).networkId, true);}public void startScan() {mWifiManager.startScan();// 得到扫描结果mWifiList = mWifiManager.getScanResults();// 得到配置好的网络连接mWifiConfigurations = mWifiManager.getConfiguredNetworks();}// 得到网络列表public List<ScanResult> getWifiList() {return mWifiList;}// 查看扫描结果public StringBuffer lookUpScan() {StringBuffer sb = new StringBuffer();for (int i = 0; i < mWifiList.size(); i++) {sb.append("Index_" + new Integer(i + 1).toString() + ":");// 将ScanResult信息转换成一个字符串包// 其中把包括:BSSID、SSID、capabilities、frequency、levelsb.append((mWifiList.get(i)).toString()).append("\n");}return sb;}public String getMacAddress() {return (mWifiInfo == null) ? "NULL" : mWifiInfo.getMacAddress();}public String getBSSID() {return (mWifiInfo == null) ? "NULL" : mWifiInfo.getBSSID();}public int getIpAddress() {return (mWifiInfo == null) ? 0 : mWifiInfo.getIpAddress();} // 得到连接的IDpublic String getSSID() {return (mWifiInfo == null) ? "" : mWifiInfo.getSSID().replace("\"", "");} // 得到连接的IDpublic int getNetWordId() {return (mWifiInfo == null) ? 0 : mWifiInfo.getNetworkId();} // 得到wifiInfo的所有信息public String getWifiInfo() {return (mWifiInfo == null) ? "NULL" : mWifiInfo.toString();}public String getGateway() {return mWifiInfo == null ? "NULL": intToIp(mWifiManager.getDhcpInfo().gateway);}private String intToIp(int paramInt) {return (paramInt & 0xFF) + "." + (0xFF & paramInt >> 8) + "."+ (0xFF & paramInt >> 16) + "." + (0xFF & paramInt >> 24);}// 添加一个网络并连接public boolean addNetWork(WifiConfiguration configuration) {int wcgId = mWifiManager.addNetwork(configuration);return mWifiManager.enableNetwork(wcgId, true);}// 断开指定ID的网络public void disConnectionWifi(int netId) {mWifiManager.disableNetwork(netId);mWifiManager.disconnect();}public WifiConfiguration createWifiInfo(String SSID, String Password,int TYPE) {WifiConfiguration config = new WifiConfiguration();config.allowedAuthAlgorithms.clear();config.allowedGroupCiphers.clear();config.allowedKeyManagement.clear();config.allowedPairwiseCiphers.clear();config.allowedProtocols.clear();config.SSID = "\"" + SSID + "\"";WifiConfiguration tempConfig = this.IsExsits(SSID);if (tempConfig != null) {mWifiManager.removeNetwork(tempConfig.networkId);}if (TYPE == 1) // WIFICIPHER_NOPASS{// config.wepKeys[0] = "";config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);// config.wepTxKeyIndex = 0;}if (TYPE == 2) // WIFICIPHER_WEP{config.hiddenSSID = true;config.wepKeys[0] = "\"" + Password + "\"";config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);config.wepTxKeyIndex = 0;}if (TYPE == 3) // WIFICIPHER_WPA  WPA2{config.preSharedKey = "\"" + Password + "\"";config.hiddenSSID = true;config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);// config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);config.status = WifiConfiguration.Status.ENABLED;}return config;}//判断密码的类别public int getType(String capabilities) //[wpa]{//[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]// [WPA2-PSK-CCMP][ESS]//[ESS]if (capabilities.contains("WPA"))return 3;else if (capabilities.contains("WEP"))return 2;elsereturn 1;}//根据SSID判断这个WIFE设置对象是否存在private WifiConfiguration IsExsits(String SSID) {List<WifiConfiguration> existingConfigs = mWifiManager.getConfiguredNetworks();for (WifiConfiguration existingConfig : existingConfigs) {if (existingConfig.SSID.equals("\"" + SSID + "\"")) {return existingConfig;}}return null;}
}

(四)主方法的类的设计

package fuxi.wifedemo;import android.content.DialogInterface;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {WifiUtil wifiUtil;//定义Wife工具类ListView listView;//显示Wife的数据列表ArrayAdapter<String> adapter;//列表的适配器List<String> wifiSSIDs = new ArrayList<>();//列表的数据WifiManager wifiManager;//Wife管理器@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);wifiUtil = new WifiUtil(this);wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);//获取Wife管理器listView = (ListView) findViewById(R.id.lv);//创建适配器,并把适配器设置到ListView中adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, wifiSSIDs);listView.setAdapter(adapter);//给ListView设置点击事件,点击后连接WifelistView.setOnItemClickListener(this);}/*** 打开Wife*/public void open(View view) {wifiUtil.openWifi();}/*** 关闭Wife*/public void close(View view) {wifiUtil.closeWifi();}/*** 扫描Wife*/List<ScanResult> wifiList = new ArrayList<>();public void scan(View view) {isClickHistory = false;//显示的列表不是历史记录//扫描先清除数据wifiSSIDs.clear();wifiList.clear();wifiUtil.startScan();//扫描WifewifiList = wifiUtil.getWifiList();//获取列表中的SSID并显示出来for (ScanResult scanResult : wifiList) {wifiSSIDs.add(scanResult.SSID);}//刷新适配器adapter.notifyDataSetChanged();}/*** 获取连接过的Wife数据*/List<WifiConfiguration> configuredNetworks = new ArrayList<>();public void getGood(View view) {isClickHistory = true;//显示的列表是历史记录//扫描先清除数据wifiSSIDs.clear();if (configuredNetworks != null) {configuredNetworks.clear();//获取历史记录configuredNetworks = wifiUtil.getConfiguration();if (configuredNetworks == null)return;for (WifiConfiguration result : configuredNetworks) {wifiSSIDs.add(result.SSID);}//刷新适配器adapter.notifyDataSetChanged();}//获取列表中的SSID并显示出来}/*** 点击Wife视图列表数据后的回调方法,这里是连接WIfe*/boolean isClickHistory = false;@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//判断是否是点击的历史记录if (isClickHistory) {boolean connOk = wifiUtil.connetionConfiguration(position);if (connOk) {Toast.makeText(MainActivity.this, "Wife连接成功", Toast.LENGTH_SHORT).show();finish();} else {Toast.makeText(MainActivity.this, "Wife连接失败", Toast.LENGTH_SHORT).show();}} else {//连接wifiScanResult sr = wifiList.get(position);//获取点击的扫描信息final String SSID = sr.SSID;//获取Wife的SSIDfinal int type = wifiUtil.getType(sr.capabilities);if (type == 1) {//没有密码的Wife情况WifiConfiguration config = wifiUtil.createWifiInfo(SSID, "", type);//第二个空就是密码wifiUtil.addNetWork(config);} else {//有密码final EditText et = new EditText(MainActivity.this);et.setHint("输入wifi密码");new AlertDialog.Builder(MainActivity.this).setTitle("设置密码").setView(et).setNeutralButton("取消", null).setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {WifiConfiguration config = wifiUtil.createWifiInfo(SSID, et.getText().toString(), type);boolean conn = wifiUtil.addNetWork(config);//判断密码是否连接成功if (conn) {Toast.makeText(MainActivity.this, "Wife连接成功", Toast.LENGTH_SHORT).show();finish();//关闭页面} else {Toast.makeText(MainActivity.this, "Wife连接失败", Toast.LENGTH_SHORT).show();}}}).create().show();}}}
}

其中上面很多过程的操作都是在工具类中做好实现了,在主方法类中只要实现逻辑调用就可以完成Wife的设计了。
       这里的WifeUtil可以直接拿去使用,也可以在里面多添加一些功能。
程序运行后,扫描蓝牙的显示界面:

点击历史连接记录,显示的界面:


点击某一个条目的Wife数据,就行连接的界面:

       输入正确的密码就可以连上Wife了,如果输入错误,它会提示你连接失败。

上面已经简单使用一个Wife程序的开发,就是功能不是很强大!

Android无线Wifi开发相关推荐

  1. 基于Wio RP2040迷你无线WiFi开发板的硬件接口技术及MicroPython控制编程基础

    Wio RP2040迷你无线WiFi开发板(Wio RP2040 mini Dev Board)是Seeed Studio公司于2021年5月推出的一款迷你无线WiFi开发板,它集成了Wio RP20 ...

  2. 树莓派Pico W无线WiFi开发板使用方法及MicroPython网络编程实践

    树莓派Pico W开发板是树莓派基金会于2022年6月底推出的一款无线WiFi开发板,它支持C/C++和MicroPython编程.本文介绍树莓派Pico W无线WiFi开发板的使用方法及MicroP ...

  3. Android中WIFI开发总结(一)

    WIFI就是一种无线联网技术,常见的是使用无线路由器.那么在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网.如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为&qu ...

  4. 【Android】Android中WIFI开发总结(一)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://smallwoniu.blog.51cto.com/3911954/1334951 ...

  5. Android无线WiFi调试项目adbwifi摆脱数据线拔插烦恼无轻松远程调试

    在我们日常Android开发中,真机调试是必不可缺的操作,但是你会不会遇到公司电脑太Low,USB接口无法使用导致手机无法连接数据线进行真机调试呢?今天给大家分享一下关于adbwifi无线调试的使用方 ...

  6. android之wifi开发

    WIFI就是一种无线联网技术,常见的是使用无线路由器.那么在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网.如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为&qu ...

  7. android之wifi开发(一)

    WIFI就是一种无线联网技术,常见的是使用无线路由器.那么在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网.如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为&qu ...

  8. 【Android】Android中WIFI开发总结(二)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://smallwoniu.blog.51cto.com/3911954/1338618 ...

  9. Android设备wifi开发

    前言 三月份新入职的公司,公司的主要业务是只能电视应用,由于公司战略需要,准备做一个tvos,里面包含有设置的系统应用,本人分到的任务是wifi这一块开发.由于之前接手的都是移动端的开发,对于wifi ...

最新文章

  1. android xml opacity,Android Drawable详解
  2. 线性模型已退场,XGBoost时代早已来
  3. Hadoop伪分布式环境搭建
  4. 特殊时期,对数据中心运营有哪些影响?
  5. MQTT.fx连接aliyun阿里云的方法
  6. JAVA程序设计----函数基础2
  7. C语言程序判断计算机的CPU大小端
  8. Anuglar中正确导入RxJS库
  9. PyQt5 关于Qt Designer的初步应用和打包
  10. mac 连接百度云服务器地址,教你怎么在 Mac 下把百度网盘映射到另一个文件夹
  11. C陷阱与缺陷阅读笔记(上)
  12. 使用git作为首页以及克隆上传创建下载删除
  13. windows上dmg转换cdr_cdr中常见问题及其解决方案
  14. 增长率用计算机怎么算,excel如何利用公式来计算平均增长率的方法
  15. 怎么用计算机算组合数c,排列组合c怎么算 公式是什么
  16. 移动端自动化测试实战(一)
  17. dex2oat过程对系统性能的影响
  18. 程序员吃饭段子Java吃完就走_爆笑段子:一朋友是个程序员,有一次和他吃饭,他愁眉苦脸的说...
  19. login-shell和non login-shell区别 & bash配置文件实验报告
  20. 阿里云智能分析套件Quick BI详细介绍_智能分析套件Quick BI特性及优势

热门文章

  1. HTML文件和SHTML文件的区别
  2. UNIX环境高级编程——select、poll和epoll
  3. 面试官:vue项目如何部署?有遇到布署服务器后刷新404问题吗?
  4. Unity内置Built-in到可编程URP函数对应整理
  5. FL Studio的入门教程——通道机架
  6. c语言幅度调制程序,模拟幅度调制系统仿真.docx
  7. Linux(CentOS7)之NFS服务器设置
  8. 如何清除茶杯中的茶垢
  9. Linux安装输入法
  10. 拉格朗日插值——基于scipy实现