废话
一直在用android studio做android开发,偶然一次机会接触到了wifi adb,试了好几个支持android studio的插件,各有优缺点,有一个本来用着好好的,突然就用不了,不懂啥情况,于是就萌生了自己写一个的想法。然后查了一下,感觉写android studio插件的话,会有点麻烦,写一个小型PC桌面程序,相对简单一些,但我也从来没写过,当然,有着多年的Java基础,也不怂,索性就,盘他。
先上源码地址:https://gitee.com/imxiaoyu_admin/WIFI-ADB.git
然后附上运行之后的效果图:
程序逻辑
参考了一下其他的插件,大概就是几个功能点:
1、用户手动输入ip和端口号,直接连接设备
2、用户先用usb连接手机,然后一键切换至wifi连接
3、连接过的手机可以保存起来(如果不保存的话,下次打开需要有限连接一次才能切换wifi连接,比较麻烦)
4、连接、断开等常规操作
5、手动设置adb程序的路径(懒得写自动检测的,索性就写个手动的,反正设置一次永久使用,问题不大)
开发环境
操作系统是win10,其他一些Jdk等必要的东西,就不列举了
1、开发工具Intellij Idea
2、adb.exe
开始编码
1、新建一个java程序
2、简单分一下包
3、引用gson工具包
网上下载一个gson.jar,然后复制到lib文件夹
点击 File->Project Structure->Libraries,然后点加号并找到gson.jar,导入完成之后如下图所示:
4、相关工具类
缓存逻辑:
因为程序比较简单,这里就不搞数据库这种花里胡哨的东西了,数据存储的方式,就采用txt文件+json的形式,即在本机的某个固定路径(这里写死D://wifi-adb-settings.txt)生成一个txt文件,用于存放相关数据的json字符串。
需要保存的,仅有adb路径和历史设备数据两项,设备详细信息我也不新建对象了,直接用Map<String,Objec>来处理了,一切从简。
跟adb的交互,则是通过命令行的方式交互,通过执行命令行并解析结果,来完成相关的交互工作。
下面放工具类,具体逻辑不多说了,都有注释,仔细看即可。
(1)CmdUtils
package com.imxiaoyu.wifi.adb.utils;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class CmdUtils {
/**
* 执行adb命令
*
* @param cmd 要执行的命令 参数
* @return 返回执行结果,区分换行
*/
public static List<String> runCmd(String cmd) {
System.out.print("\n执行命令:" + cmd);
List<String> list = new ArrayList<>();
Process proc = null;
BufferedReader reader;
String line = null;
Runtime runtime = Runtime.getRuntime();
try {
proc = runtime.exec(cmd);
if (proc != null) {
reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while ((line = reader.readLine()) != null) {
if (line.length() > 1) {
list.add(line);
}
}
}
} catch (Exception e) {
System.out.print("执行命令:" + cmd + "出错啦!");
return null;
}
System.out.print("执行结果:" + new Gson().toJson(list));
return list;
}
}
(2)ConnectUtils
package com.imxiaoyu.wifi.adb.utils;
import com.google.gson.Gson;
import javax.swing.*;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ConnectUtils {
/**
* 链接设备
* @param name
* @return
*/
public static boolean connect(String name) {
String cmd = SettingsUtils.getSettings().getWifiAdbPath() + "/adb.exe " + "connect " + name;
List<String> list = CmdUtils.runCmd(cmd);
String str = new Gson().toJson(list);
if (str.indexOf("connected to") > -1) {
//链接成功
return true;
}
JOptionPane.showMessageDialog(null, "目标设备拒接,无法链接。", "链接失败", JOptionPane.ERROR_MESSAGE);
return false;
}
/**
* 断开设备
* @param name
* @return
*/
public static boolean disconnect(String name) {
String cmd = SettingsUtils.getSettings().getWifiAdbPath() + "/adb.exe " + "disconnect " + name;
List<String> list = CmdUtils.runCmd(cmd);
String str = new Gson().toJson(list);
if (str.indexOf("disconnected") > -1) {
//断开成功
return true;
}
JOptionPane.showMessageDialog(null, "设备不存在。", "断开链接失败", JOptionPane.ERROR_MESSAGE);
return false;
}
/**
* 解析一个usb设备的ip地址,不带端口号
*
* @return
*/
public static String getDeviceIp(String name) {
String cmd = SettingsUtils.getSettings().getWifiAdbPath() + "/adb.exe" + " -s " + name + " shell ifconfig wlan0 ";
List<String> list = CmdUtils.runCmd(cmd);
if (list.size() < 2) {
return null;
}
String str = list.get(1);//ip地址在第二行,实例参数: inet addr:192.168.22.11 Bcast:192.168.22.255 Mask:255.255.255.0
Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher(str);
str = m.replaceAll(" ");//将多个连续的空格只保留一个
str = str.replace(":", " ");
String[] strList = str.split(" ");
System.out.print("\n读取到的ip地址:" + strList[3]);
return strList[3];
}
/**
* 给一个设备设置一个默认端口,默认5555,设置好了之后就可以直接通过ip+端口链接
*
* @param name
* @param port
* @return
*/
public static void setDevicePort(String name, String port) {
String cmd = SettingsUtils.getSettings().getWifiAdbPath() + "/adb.exe" + " -s " + name + " tcpip " + port;
CmdUtils.runCmd(cmd);
}
/**
* 判定一个设备是否是usb链接
*
* @param name
* @return true-usb链接 false-wifi链接
*/
public static boolean isUsb(String name) {
if (name.indexOf(":") == -1) {
//如果设备的名称带有冒号的,证明是带有端口的,也就不是usb的方式链接的了
return true;
}
return false;
}
/**
* 判定一个usb设备是否已经链接了wifi
*
* @param deviceList
* @param name
* @return true-usb链接 false-wifi链接
*/
public static boolean isUsbConnectWifi(List<Map<String, Object>> deviceList, String name) {
//判定逻辑:先获取这个有线设备的ip地址,如果现有的设备列表已经存在了这个ip地址,证明这个有线设备已经通过wifi链接了
String ip = getDeviceIp(name);
for (int i = 0; i < deviceList.size(); i++) {
String deviceName = deviceList.get(i).get("name") + "";
if (deviceName.startsWith(ip)) {
return true;
}
}
return false;
}
/**
* 判定一个wifi设备是否已经链接了
*
* @param deviceList
* @param name
* @return true-usb链接 false-wifi链接
*/
public static boolean isWifiConnect(List<Map<String, Object>> deviceList, String name) {
//逻辑:如果这个wifi设备已经在当前的设备列表里,那就是已连接了
for (int i = 0; i < deviceList.size(); i++) {
String deviceName = deviceList.get(i).get("name") + "";
if (deviceName.startsWith(name)) {
return true;
}
}
return false;
}
}
(3)SettingsEntity
package com.imxiaoyu.wifi.adb.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class SettingsEntity {
private String wifiAdbPath = "";
private List<Map<String, Object>> phoneList=new ArrayList<>();
public String getWifiAdbPath() {
return wifiAdbPath;
}
public void setWifiAdbPath(String wifiAdbPath) {
this.wifiAdbPath = wifiAdbPath;
}
public List<Map<String, Object>> getPhoneList() {
return phoneList;
}
public void setPhoneList(List<Map<String, Object>> phoneList) {
this.phoneList = phoneList;
}
}
(4)SettingsUtils
package com.imxiaoyu.wifi.adb.utils;
import com.google.gson.Gson;
import javax.swing.*;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SettingsUtils {
private static Gson gson = new Gson();
private static final String SETTINGS_PATH = "D://wifi-adb-settings.txt";//用于保存数据的txt文件的目录
/**
* 获取当前链接的设备的设备列表
*
* @return
*/
public static List<Map<String, Object>> getAllDevice() {
List<Map<String, Object>> deviceList = new ArrayList<>();
SettingsEntity entity = getSettings();
String cmd = entity.getWifiAdbPath() + "/adb.exe " + "devices -l";//获取列表的命令
List<String> cmdList = CmdUtils.runCmd(cmd);
//运行adb.exe devices -l 这个命令之后,从返回的结果中解析出设备的相关信息
for (int i = 1; i < cmdList.size(); i++) {
//跳过第一行
Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher(cmdList.get(i));
String str = m.replaceAll(" ");//将多个连续的空格只保留一个
str = str.replace(":", " ");//将冒号抓换成空格,方便解析
if (str.indexOf(".") > -1) {
//如果包含有小数点,证明名字是带端口的,这时候需要把第一个空格还原为冒号
str = str.replaceFirst(" ", ":");
}
System.out.print("\n解析前:" + str);
Map<String, Object> map = new HashMap<>();
String[] list = str.split(" ");
map.put("name", list[0]);
map.put("device_product", list[3]);
map.put("model", list[5]);
map.put("device", list[7]);
map.put("transport_id", list[9]);
deviceList.add(map);
}
return deviceList;
}
/**
* 将一个已连接的设备保存起来
*
* @param map
*/
public static void saveDevice(Map<String, Object> map) {
if (isHaveDevice(map)) {
JOptionPane.showMessageDialog(null, "设备已存在", "保存失败", JOptionPane.ERROR_MESSAGE);
return;
}
SettingsEntity entity = getSettings();
map.put("id", UUID.randomUUID().toString());//保存的时候给加一个唯一id,方便删除
entity.getPhoneList().add(map);
setSettings(entity);
//保存成功
}
/**
* 根据id,删除一个已保存的设备
*
* @param id
*/
public static void removeDevice(String id) {
SettingsEntity entity = getSettings();
List<Map<String, Object>> list = getSettings().getPhoneList();
for (int i = 0; i < list.size(); i++) {
if (list.get(i).get("id").equals(id)) {
list.remove(i);
}
entity.setPhoneList(list);
setSettings(entity);
return;
}
//删除成功
}
/**
* 判定一个设备是否已经存在
*
* @param map
* @return
*/
public static boolean isHaveDevice(Map<String, Object> map) {
List<Map<String, Object>> deviceList = getSettings().getPhoneList();
if (deviceList == null) {
deviceList = new ArrayList<>();
}
boolean isHave = false;//是否存在
for (int i = 0; i < deviceList.size(); i++) {
if (deviceList.get(i).get("name").equals(map.get("name")) && deviceList.get(i).get("model").equals(map.get("model"))) {
isHave = true;//这个设备已存在
}
}
return isHave;
}
/**
* 获取保存的数据
*
* @return
*/
public static SettingsEntity getSettings() {
SettingsEntity settingsEntity;
String str = readString();
settingsEntity = gson.fromJson(str, SettingsEntity.class);
if (settingsEntity == null) {
settingsEntity = new SettingsEntity();
}
return settingsEntity;
}
/**
* 写入保存数据
*
* @param entity
*/
public static void setSettings(SettingsEntity entity) {
writeString(gson.toJson(entity));
}
/**
* 从文件中读取保存数据的json字符串
*
* @return
*/
private static String readString() {
File file = new File(SETTINGS_PATH);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try (FileReader reader = new FileReader(SETTINGS_PATH);
BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言
) {
String allStr = "";
String line;
//网友推荐更加简洁的写法
while ((line = br.readLine()) != null) {
// 一次读入一行数据
// System.out.println(line);
allStr += line;
}
return allStr;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 将json字符串写入到txt文件中
*
* @param settingsStr
*/
private static void writeString(String settingsStr) {
try {
File writeName = new File(SETTINGS_PATH); // 相对路径,如果没有则要建立一个新的output.txt文件
writeName.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖
try (FileWriter writer = new FileWriter(writeName);
BufferedWriter out = new BufferedWriter(writer)
) {
out.write(settingsStr); // \r\n即为换行
out.flush(); // 把缓存区内容压入文件
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
5、写页面交互
其实写页面是我耗时最久的地方,可能是写习惯android了,切换到这边,写列表的时候,习惯性使用jlist这个控件,后来试了挺多次了,效果不太满意,后来查了一下,才转过来用jtabel,对是用对了,但是这个坑也挺坑的,反正就是遇到各种问题,耗费了不少时间。
编写过程也不多少了,直接看代码吧,都有注释,先上一张截图,然后是源码。
页面相关的操作逻辑,我都放到了IndexView这个页面里,可能会显得稍乱一些。
package com.imxiaoyu.wifi.adb.view;
import com.imxiaoyu.wifi.adb.utils.ConnectUtils;
import com.imxiaoyu.wifi.adb.utils.SettingsEntity;
import com.imxiaoyu.wifi.adb.utils.SettingsUtils;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class IndexView {
private JPanel jPanel;
private JTextField tf_adb_path;
private JButton btn_adb_path;
private JButton btn_refresh;
private JTable tb_now;
private JTable tb_history;
private JButton btn_test_connect;
private JTextField tf_ip_port;
private List<Map<String, Object>> nowDeviceList = new ArrayList<>();
private List<Map<String, Object>> historyDeviceList = new ArrayList<>();
public void startView() {
JFrame frame = new JFrame("Wifi Adb");
frame.setContentPane(jPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
frame.setSize(new Dimension(880, 500));
btn_adb_path.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
//设置一下adb.exe的路径
JFileChooser fileChooser = new JFileChooser("D:\\");
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = fileChooser.showOpenDialog(fileChooser);
if (returnVal == JFileChooser.APPROVE_OPTION) {
String filePath = fileChooser.getSelectedFile().getAbsolutePath();//这个就是你选择的文件夹的路径
tf_adb_path.setText(filePath);
System.out.print("\n选中的路径:" + filePath);
SettingsEntity entity = SettingsUtils.getSettings();
entity.setWifiAdbPath(filePath);
SettingsUtils.setSettings(entity);
}
}
});
btn_test_connect.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//通过手动输入ip和端口的形式,直接连接设备
String deviceName=tf_ip_port.getText();
ConnectUtils.connect(deviceName);
initList();
}
});
btn_refresh.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
//刷新列表
initList();
}
});
//初始化adv.exe的路径信息
SettingsEntity entity = SettingsUtils.getSettings();
tf_adb_path.setText(entity.getWifiAdbPath());
initList();
}
private void initList() {
nowDeviceList = SettingsUtils.getAllDevice();
NowListModel listModel = new NowListModel();
tb_now.setModel(listModel);//设置需要显示的数据
tb_now.setRowHeight(36);
//这个setCellEditor和setCellRenderer必须分别new,不然的话点击按钮的时候会有点小问题
tb_now.getColumnModel().getColumn(3).setCellEditor(new NowListEditor());//加入点击监听
tb_now.getColumnModel().getColumn(3).setCellRenderer(new NowListEditor());//加入操作按钮
tb_now.setRowSelectionAllowed(false);
historyDeviceList = SettingsUtils.getSettings().getPhoneList();
HistoryListModel historyListModel = new HistoryListModel();
tb_history.setModel(historyListModel);
tb_history.setRowHeight(36);
tb_history.getColumnModel().getColumn(3).setCellEditor(new HistoryListEditor());
tb_history.getColumnModel().getColumn(3).setCellRenderer(new HistoryListEditor());
tb_history.setRowSelectionAllowed(false);
}
public class NowListModel extends AbstractTableModel {
/**
* 得到表格行数
*/
@Override
public int getRowCount() {
if (nowDeviceList.size() == 0) {
//列表空的话,标题也不显示
return 0;
}
return nowDeviceList.size() + 1;
}
/**
* 重写方法,得到表格列数
*/
@Override
public int getColumnCount() {
return 4;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex == 0) {
if (columnIndex == 0) {
return "型号";
}
if (columnIndex == 1) {
return "设备名称";
}
if (columnIndex == 2) {
return "transport_id";
}
if (columnIndex == 3) {
return "操作";
}
}
if (columnIndex == 0) {
return nowDeviceList.get(rowIndex - 1).get("model");
}
if (columnIndex == 1) {
return nowDeviceList.get(rowIndex - 1).get("name");
}
if (columnIndex == 2) {
return nowDeviceList.get(rowIndex - 1).get("transport_id");
}
return "";
}
@Override
public boolean isCellEditable(int row, int column) {
// 带有按钮列的功能这里必须要返回true不然按钮点击时不会触发编辑效果,也就不会触发事件。
if (column == 3) {
return true;
} else {
return false;
}
}
}
public class HistoryListModel extends AbstractTableModel {
/**
* 得到表格行数
*/
@Override
public int getRowCount() {
if (historyDeviceList.size() == 0) {
return 0;
}
return historyDeviceList.size() + 1;
}
/**
* 重写方法,得到表格列数
*/
@Override
public int getColumnCount() {
return 4;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex == 0) {
if (columnIndex == 0) {
return "型号";
}
if (columnIndex == 1) {
return "设备名称";
}
if (columnIndex == 3) {
return "操作";
}
if (columnIndex == 2) {
return "transport_id";
}
}
if (columnIndex == 1) {
return historyDeviceList.get(rowIndex - 1).get("name");
}
if (columnIndex == 0) {
return historyDeviceList.get(rowIndex - 1).get("model");
}
if (columnIndex == 2) {
return historyDeviceList.get(rowIndex - 1).get("transport_id");
}
return "";
}
@Override
public boolean isCellEditable(int row, int column) {
// 带有按钮列的功能这里必须要返回true不然按钮点击时不会触发编辑效果,也就不会触发事件。
if (column == 3) {
return true;
} else {
return false;
}
}
}
public class NowListEditor extends AbstractCellEditor implements TableCellRenderer,
TableCellEditor {
private JPanel panel;
private JButton btnSave = null;
private JButton btnDis = null;
private JButton btnConnect = null;
private int clickRow;
public NowListEditor() {
initButton();
initPanel();
panel.add(btnConnect);
panel.add(btnDis);
panel.add(btnSave);
}
private void initButton() {
/**
* 初始化按钮
*/
btnConnect = new JButton("链接");
btnDis = new JButton("断开");
btnSave = new JButton("保存");
/**
* 设置按钮监听
*/
btnConnect.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("\n链接");
System.out.print(";clickRow:" + clickRow);
String deviceName = nowDeviceList.get(clickRow - 1).get("name") + "";
String ip = ConnectUtils.getDeviceIp(deviceName);
String port = "5555";
ConnectUtils.setDevicePort(deviceName, port);
ConnectUtils.connect(ip + ":" + port);
initList();
}
});
btnDis.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("\n断开");
System.out.print(";clickRow:" + clickRow);
ConnectUtils.disconnect(nowDeviceList.get(clickRow - 1).get("name") + "");
initList();
}
});
btnSave.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("\n保存");
System.out.print(";clickRow:" + clickRow);
SettingsUtils.saveDevice(nowDeviceList.get(clickRow - 1));
initList();
}
});
}
/**
* 初始化画板
*/
private void initPanel() {
panel = new JPanel();
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
/**
* 这里是处理显示
*/
panel.setBackground(new Color(255, 255, 255));
if (row != 0) {
panel.removeAll();
String deviceName = nowDeviceList.get(row - 1).get("name") + "";
if (ConnectUtils.isUsb(deviceName)) {
//这是一个有线设备
if (!ConnectUtils.isUsbConnectWifi(nowDeviceList, deviceName)) {
//这个有限设备还没链接wifi
panel.add(btnConnect);
}
} else {
//这是一个wifi设备
panel.add(btnDis);
if (!SettingsUtils.isHaveDevice(nowDeviceList.get(row - 1))) {
//这个wifi设备还没有保存
panel.add(btnSave);
}
}
return panel;
}
return null;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
/**
* 这里是处理点击
*/
clickRow = row;
panel.setBackground(new Color(255, 255, 255));
if (row != 0) {
panel.removeAll();
String deviceName = nowDeviceList.get(row - 1).get("name") + "";
if (ConnectUtils.isUsb(deviceName)) {
System.out.print("\n有线设备:"+deviceName);
//这是一个有线设备
if (!ConnectUtils.isUsbConnectWifi(nowDeviceList, deviceName)) {
//这个有限设备还没链接wifi
panel.add(btnConnect);//显示连接按钮
}
//如果有线设备已经链接了,就不再显示连接按钮
} else {
//这是一个wifi设备
panel.add(btnDis);//如果列表里面有wifi设备,证明肯定是链接状态了的,所以只需要显示断开按钮
if (!SettingsUtils.isHaveDevice(nowDeviceList.get(row - 1))) {
//这个wifi设备还没有保存
panel.add(btnSave);//没保存就显示保存按钮,已保存则不显示
}
}
return panel;
}
return null;
}
@Override
public Object getCellEditorValue() {
return null;
}
}
public class HistoryListEditor extends AbstractCellEditor implements TableCellRenderer,
TableCellEditor {
private JPanel panel;
private JButton btnSave = null;
private JButton btnDis = null;
private JButton btnConnect = null;
private int clickRow;
public HistoryListEditor() {
initButton();
initPanel();
panel.add(btnConnect);
panel.add(btnDis);
panel.add(btnSave);
}
private void initButton() {
/**
* 初始化按钮
*/
btnConnect = new JButton("链接");
btnDis = new JButton("断开");
btnSave = new JButton("删除");
/**
* 监听点击
*/
btnConnect.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("\n链接");
ConnectUtils.connect(historyDeviceList.get(clickRow - 1).get("name") + "");
System.out.print(";clickRow:" + clickRow);
initList();
}
});
btnDis.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("\n断开");
ConnectUtils.disconnect(historyDeviceList.get(clickRow - 1).get("name") + "");
System.out.print(";clickRow:" + clickRow);
initList();
}
});
btnSave.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("\n删除");
System.out.print(";clickRow:" + clickRow);
SettingsUtils.removeDevice(historyDeviceList.get(clickRow - 1).get("id") + "");
initList();
}
});
}
/**
* 初始化画板
*/
private void initPanel() {
panel = new JPanel();
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
panel.setBackground(new Color(255, 255, 255));
if (row != 0) {
panel.removeAll();
String deviceName=historyDeviceList.get(row-1).get("name")+"";
if(ConnectUtils.isWifiConnect(nowDeviceList,deviceName)){
System.out.print("wifi已连接");
//这个wifi设备已经链接
panel.add(btnDis);//已连接,显示断开按钮
}else{
//还没链接
panel.add(btnConnect);//未连接,显示连接按钮
}
panel.add(btnSave);//显示删除按钮
return panel;
}
return null;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
clickRow = row;
panel.setBackground(new Color(255, 255, 255));
if (row != 0) {
panel.removeAll();
String deviceName=historyDeviceList.get(row-1).get("name")+"";
if(ConnectUtils.isWifiConnect(nowDeviceList,deviceName)){
//这个wifi设备已经链接
panel.add(btnDis);//已连接,显示断开按钮
}else{
//还没链接
panel.add(btnConnect);//未连接,显示连接按钮
}
panel.add(btnSave);//显示删除按钮
return panel;
}
return null;
}
@Override
public Object getCellEditorValue() {
return null;
}
}
}
6、导出可运行的jar程序
点击Build->Build Artifacts->All Artifacts->Build
Idea会自动在out目录中生成jar包