最近公司再做智能音箱项目。准备airkiss和声波配网进行二选一。airkiss是通过wifi广播的形式进行传输ssid和pwd。测试下来抗干扰性好。声波配网简单。不需要有wifi只要有mic输入解码即可,所以自己移植了网址
http://www.sinvoice.com/上面的Android sdk进行声波联网测试。
这个公司由于收费牵扯到版权。所以有商业化用到他们公司产品请联系sinvoice公司。本人开发只是做简单的测试。
有关声波配网的原理和介绍网上很多。所以这里不多介绍。
本文代码主要由两部分组成–声波编码和解码 和 wifi联网,声波编解码主要是sinvoice公司的代码可以到这个网址下载http://www.sinvoice.com/。我下载的是
这个SinVoice_Android_v2.2 版本。
package com.example.sinvoicedemo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.libra.sinvoice.Common;
import com.libra.sinvoice.LogHelper;
import com.libra.sinvoice.SinVoicePlayer;
import com.libra.sinvoice.SinVoiceRecognition;
import com.libra.sinvoice.WifiAutoConnectManager;
public class MainActivity extends Activity implements
SinVoiceRecognition.Listener, SinVoicePlayer.Listener ,WifiAutoConnectManager.WifiConnectListenner{
private final static String TAG = "MainActivityxx";
private final static int MSG_SET_RECG_TEXT = 1;
private final static int MSG_RECG_START = 2;
private final static int MSG_RECG_END = 3;
private final static int MSG_PLAY_TEXT = 4;
private final static int[] TOKENS = { 32, 32, 32, 32, 32, 32 };
private final static String TOKENS_str = "Beeba20141";
private final static int TOKEN_LEN = TOKENS.length;
private final static String BAKCUP_LOG_PATH = "/sinvoice_backup";
private Handler mHanlder;
private SinVoicePlayer mSinVoicePlayer;
private SinVoiceRecognition mRecognition;
private WifiAutoConnectManager mWifiConnectManager;
//这个是我自己加的主要用于wifi联网的管理
private boolean mIsReadFromFile;
private String mSdcardPath;
private PowerManager.WakeLock mWakeLock;
private EditText mPlayTextView;
private EditText mPlayTextView1;
private TextView mRecognisedTextView;
// private TextView mRegState;
private String mPlayText;
private char mRecgs[] = new char[100];
private int mRecgCount;
static {
System.loadLibrary("sinvoice");
LogHelper.d(TAG, "sinvoice jnicall loadlibrary");
}
//真正的编解码主要通过c语音库进行处理的。java代码只是做逻辑处理
//所以这里加载编解码库
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIsReadFromFile = false;
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, TAG);
mSdcardPath = Environment.getExternalStorageDirectory().getPath();
mSinVoicePlayer = new SinVoicePlayer();
mSinVoicePlayer.init(this);
mSinVoicePlayer.setListener(this);
//编码器初始化
mWifiConnectManager = new WifiAutoConnectManager(wifiManager);
mWifiConnectManager.setListenner(this);
//wifi管理初始化
mRecognition = new SinVoiceRecognition();
mRecognition.init(this);
mRecognition.setListener(this);
mRecognition.start(TOKEN_LEN, mIsReadFromFile);
//解码器初始化
mPlayTextView = (EditText) findViewById(R.id.playtext);
mPlayTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
mPlayTextView1 = (EditText) findViewById(R.id.playtext1);
mPlayTextView1.setMovementMethod(ScrollingMovementMethod.getInstance());
mRecognisedTextView = (TextView) findViewById(R.id.regtext);
mHanlder = new RegHandler(this);
Button playStart = (Button) findViewById(R.id.start_play);
playStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
try {
// mWifiConnectManager.connect("lvbiao","lb123456",WifiCipherType.WIFICIPHER_WPA);
Log.e("PP","come here");
StringBuilder sb=new StringBuilder();
byte[] strs = mPlayTextView.getText().toString().getBytes("UTF8");
byte[] strs1 = mPlayTextView1.getText().toString().getBytes("UTF8");
if ( null != strs ) {
int len = strs.length + strs1.length + 2;
int []tokens = new int[len];
int maxEncoderIndex = mSinVoicePlayer.getMaxEncoderIndex();
LogHelper.d(TAG, "maxEncoderIndex:" + maxEncoderIndex);
String encoderText = mPlayTextView.getText().toString();
sb.append(encoderText);
String encoderText1 = mPlayTextView1.getText().toString();
sb.append("A@");
sb.append(encoderText1);
for ( int i = 0; i < len; ++i ) {
if ( maxEncoderIndex < 255 ) {
tokens[i] = Common.DEFAULT_CODE_BOOK.indexOf(sb.charAt(i));
} else {
tokens[i] = strs[i];
}
}
mSinVoicePlayer.play(tokens, len, false, 2000);
} else {
mSinVoicePlayer.play(TOKENS, TOKEN_LEN, false, 2000);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
});
sinvoice 解码和编码是一个程序。都在主界面上。通过按键可以开启和关闭解码和编码。
这里的SinVoiceRecognition 主要完成声波的解码辅助工作,前面说过 真正的解码在so库中完成。所以SinVoiceRecognition 主要功能是录音声波。并将录音声波的文件发送给so库。然后接收解码完成的声波结果ascii装成相应的字符。
Button recognitionStart = (Button) findViewById(R.id.start_reg);
recognitionStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
mRecognition.start(TOKEN_LEN, mIsReadFromFile);
}
});
这里打开语音识别
public void start(final int tokenCount, final boolean isReadFromFile) {
if (STATE_STOP == mState) {
mState = STATE_START;
mBufferQueue.set();
mRecognitionThread = new Thread() {
@Override
public void run() {
mRecognition.start(tokenCount);
}
};
if (null != mRecognitionThread) {
mRecognitionThread.start();
}
mRecordThread = new Thread() {
@Override
public void run() {
mRecord.start(isReadFromFile);
}
};
if (null != mRecordThread) {
mRecordThread.start();
}
}
}
mRecognition.start(TOKEN_LEN, mIsReadFromFile)通过开启mRecordThread进行录音和mRecognition进行解码两个线程做大部分工作。
先看mRecordThread的代码
public void start(boolean isReadFromFile) {
if (STATE_STOP == mState) {
if (isReadFromFile) {
recordFromFile();
} else {
recordFromDevice();
}
}
}
这里没有特殊选择的话会执行recordFromDevice
private void recordFromDevice() {
LogHelper.d(TAG, "recordFromDevice Start");
if (mBufferSize > 0) {
AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, mSampleRate, mChannelConfig, mAudioEncoding, mBufferSize * 5);
if (null != record) {
try {
mState = STATE_START;
LogHelper.d(TAG, "record start");
record.startRecording();
LogHelper.d(TAG, "record start 1");
if (null != mCallback) {
if (null != mListener) {
mListener.onStartRecord();
}
while (STATE_START == mState) {
BufferData data = mCallback.getRecordBuffer();
if (null != data) {
if (null != data.mData) {
int bufferReadResult = record.read(data.mData, 0, mBufferSize);
LogHelper.d(TAG, "read record:" + bufferReadResult);
data.setFilledSize(bufferReadResult);
mCallback.freeRecordBuffer(data);
} else {
// end of input
LogHelper.d(TAG, "get end input data, so stop");
break;
}
} else {
LogHelper.e(TAG, "get null data");
break;
}
}
if (null != mListener) {
mListener.onStopRecord();
}
}
LogHelper.d(TAG, "stop record");
record.stop();
LogHelper.d(TAG, "release record");
record.release();
LogHelper.d(TAG, "record stop");
} catch (IllegalStateException e) {
e.printStackTrace();
LogHelper.e(TAG, "start record error");
}
mState = STATE_STOP;
}
} else {
LogHelper.e(TAG, "bufferSize is too small");
}
LogHelper.d(TAG, "recordFromDevice End");
}
主要工作就是打开一个new AudioRecord进行录音
data.setFilledSize(bufferReadResult);会把录音数据放到BufferData中
解码库会从BufferData获取录音数据进行解码。
public void start(int tokenCount) {
if (STATE_STOP == mState) {
mConsumedSize = 0;
mVoiceDecoder.initVR(mContext, "com.sinvoice.demo", "SinVoice");
//开启语音识别器。这是native方法。打开的是c语言中的解码器
LogHelper.d(
TAG,
"Voice Recogintiono start threadid:"
+ Thread.currentThread());
if (null != mCallback) {
mState = STATE_START;
if (null != mListener) {
mListener.onStartRecognition();
}
try {
String sdcardPath = Environment.getExternalStorageDirectory().getPath();
if ( !TextUtils.isEmpty(sdcardPath) ) {
mFileOut = new FileOutputStream(String.format("%s/record.pcm", sdcardPath));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
LogHelper.d(TAG, "Voice Recogintion startVR");
mVoiceDecoder.startVR(mSampleRate, tokenCount);//配置识别采样率和采样数
LogHelper.d(TAG, "Voice Recogintion start VR End");
while (STATE_START == mState) {
BufferData data = mCallback.getRecognitionBuffer();//获取录音数据
if (null != data) {
if (null != data.mData) {
LogHelper.d(TAG, "putData data:" + data + " filledSize:" + data.getFilledSize());
mConsumedSize += data.getFilledSize();
LogHelper.d(TAG, "VoiceRecognition putData data mConsumedSize:" + mConsumedSize);
mVoiceDecoder.putData(data.mData, data.getFilledSize());
//进行解码
mCallback.freeRecognitionBuffer(data);
if (null != mFileOut) {
try {
mFileOut.write(data.mData);
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
LogHelper.d(TAG, "end input buffer, so stop");
break;
}
} else {
LogHelper.e(TAG, "get null recognition buffer");
break;
}
}
mVoiceDecoder.stopVR();
if (null != mFileOut) {
try {
mFileOut.close();
mFileOut = null;
} catch (IOException e) {
e.printStackTrace();
}
}
mState = STATE_STOP;
if (null != mListener) {
mListener.onStopRecognition();
}
}
mVoiceDecoder.uninitVR();
}
}
解码的结果会通过VoiceDecoder.java的onRecognized 返回结果
private void onRecognized(int index) {
LogHelper.d("VoiceRecognition", "onRecognized:" + index);
if (null != mCallback) {
mCallback.onVoiceDecoderResult(index);
}
}
这里处理返回结果显示到手机上和数据处理
private static class RegHandler extends Handler {
private StringBuilder mTextBuilder = new StringBuilder();
private MainActivity mAct;
public RegHandler(MainActivity act) {
mAct = act;
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_RECG_TEXT:
char ch = (char) msg.arg1;
// mTextBuilder.append(ch);
mAct.mRecgs[mAct.mRecgCount++] = ch;
break;
case MSG_RECG_START:
// mTextBuilder.delete(0, mTextBuilder.length());
mAct.mRecgCount = 0;
break;
case MSG_RECG_END:
Log.e("PP", "recognition end gIsError:" + msg.arg1);
if ( mAct.mRecgCount > 0 ) {
byte[] strs = new byte[mAct.mRecgCount];
for ( int i = 0; i < mAct.mRecgCount; ++i ) {
strs[i] = (byte)mAct.mRecgs[i];
}
try {
//解码结果
String strReg = new String(strs, "UTF8");
String[] wifi_info = strReg.split("A@");
// 解码分割。我这边是以A@作为分隔符。比如
//sandiskA@lb12345 则 sandisk为ssid lb12345 为pwd
String ssid = wifi_info[0];
String pwd = wifi_info[1];
Log.e("PP","recv ssid ==" + ssid);
Log.e("PP","recv pwd ==" + pwd);
mAct.call(ssid, pwd);//进行wifi连接
// Log.e("PP","recv ssid ==" + ssid);
// Log.e("PP","recv pwd ==" + pwd);
if (msg.arg1 >= 0) {
Log.d(TAG, "reg ok!!!!!!!!!!!!");
if (null != mAct) {
mAct.mRecognisedTextView.setText(strReg);
// mAct.mRegState.setText("reg ok(" + msg.arg1 + ")");
}
} else {
Log.d(TAG, "reg error!!!!!!!!!!!!!");
mAct.mRecognisedTextView.setText(strReg);
// mAct.mRegState.setText("reg err(" + msg.arg1 + ")");
// mAct.mRegState.setText("reg err");
}
} catch (Exception e) {
e.printStackTrace();
}
}
break;
case MSG_PLAY_TEXT:
// mAct.mPlayTextView.setText(mAct.mPlayText);
break;
}
super.handleMessage(msg);
}
}
private void call(String ssid, String pwd) {
mWifiConnectManager.connect(ssid,pwd, WifiCipherType.WIFICIPHER_WPA);
}
WifiAutoConnectManager主要工作是在SinVoiceRecognition 获取到解码的ssid和pwd后。进行wifi主动连接
package com.libra.sinvoice;
import java.lang.reflect.Method;
import java.util.List;
//import com.lgshouyou.vrclient.config.//DebugUtils;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import com.example.sinvoicedemo.WifiCipherType;
public class WifiAutoConnectManager {
private static String TAG = WifiAutoConnectManager.class.getName();
private WifiManager wifiManager;
private WifiConnectListenner listenner;
public interface WifiConnectListenner{
void connectFail();
void connectSuc();
}
public void setListenner(WifiConnectListenner listener){
this.listenner = listener;
}
// 构造函数
public WifiAutoConnectManager(WifiManager wifiManager) {
this.wifiManager = wifiManager;
}
// 提供一个外部接口,传入要连接的无线网
public void connect(String ssid, String password, WifiCipherType type) {
Thread thread = new Thread(new ConnectRunnable(ssid, password, type));
thread.start();
}
// 查看以前是否也配置过这个网络
private WifiConfiguration isExsits(String SSID) {
List<WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
if(existingConfigs != null){
for (WifiConfiguration existingConfig : existingConfigs) {
if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
return existingConfig;
}
}
}
return null;
}
private WifiConfiguration createWifiInfo(String SSID, String Password, WifiCipherType Type) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\"";
if (Type == WifiCipherType.WIFICIPHER_NOPASS) {//modify 20161219加上屏蔽的两行会导致返回netId为-1
// config.wepKeys[0] = "";
config.hiddenSSID = true;
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
// config.wepTxKeyIndex = 0;
//DebugUtils.printInfo(TAG, "无密配置");
}else if (Type == WifiCipherType.WIFICIPHER_WEP) {
config.preSharedKey = "\"" + Password + "\"";
config.hiddenSSID = true;
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;
}else if (Type == WifiCipherType.WIFICIPHER_WPA) {
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;
}else if(Type == WifiCipherType.WIFICIPHER_WPA2){
config.preSharedKey = "\"" + Password + "\"";
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
config.status = WifiConfiguration.Status.ENABLED;
}else{
return null;
}
return config;
}
// 打开wifi功能
private boolean openWifi() {
boolean bRet = true;
if (!wifiManager.isWifiEnabled()) {
bRet = wifiManager.setWifiEnabled(true);
//DebugUtils.debug(TAG, "openWifi bRet: " + bRet);
}
return bRet;
}
class ConnectRunnable implements Runnable {
private String ssid;
private String password;
private WifiCipherType type;
public ConnectRunnable(String ssid, String password, WifiCipherType type) {
this.ssid = ssid;
this.password = password;
this.type = type;
//DebugUtils.debug(TAG, "ssid: " + ssid + " password: " + password + " type: " + type);
}
@Override
public void run() {
// 打开wifi
openWifi();
// 开启wifi功能需要一段时间(我在手机上测试一般需要1-3秒左右),所以要等到wifi
// 状态变成WIFI_STATE_ENABLED的时候才能执行下面的语句
while (wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING) {
try {
// 为了避免程序一直while循环,让它睡个100毫秒检测……
Thread.sleep(100);
//DebugUtils.debug(TAG, "wifi已经打开");
} catch (InterruptedException ie) {
}
}
WifiConfiguration wifiConfig = createWifiInfo(ssid, password, type);
//DebugUtils.debug(TAG, "wifiConfig: " + wifiConfig);
if (wifiConfig == null) {
return;
}
WifiConfiguration tempConfig = isExsits(ssid);
if (tempConfig != null) {
//DebugUtils.debug(TAG, "配置过ssid");
wifiManager.removeNetwork(tempConfig.networkId);
}
int netID = wifiManager.addNetwork(wifiConfig);
//DebugUtils.printInfo(TAG, "netID: " + netID);
/*
* DisableOthers 为true的时候就表示在连接networkId的时候,拒绝连接其他的wifiap,
* 也就是说只连接当前的wifiap,如果连不上也不会去连接其他的wifiap
* 而为false的时候就表示连接当前wifiap,如果连不上,就去连接其他的wifiap
* */
if (-1 != netID){// 表示可以分配新的ID成功
Method connectMethod = connectWifiByReflectMethod(netID); //解决部分手机不能连接热点的情况不能单纯的使用enableNetwork方法
if (connectMethod == null) {
//DebugUtils.printInfo(TAG, "connect wifi by enableNetwork method");
// 通用API
boolean b = wifiManager.enableNetwork(netID, true);
if (b){// 链接成功
listenner.connectSuc();
//DebugUtils.printInfo(TAG, "成功连接热点");
}else{
listenner.connectFail();
}
}else{
listenner.connectSuc();
}
// boolean b = wifiManager.enableNetwork(netID, true);
// if (b){// 链接成功
//
// listenner.connectSuc();
// //DebugUtils.debug(TAG, "成功连接热点");
// }else{
// listenner.connectFail();
// }
}else{
listenner.connectFail();
}
}
}
/**
* 通过反射出不同版本的connect方法来连接Wifi
*
* @author jiangping.li
* @param netId
* @return
* @since MT 1.0
*
*/
private Method connectWifiByReflectMethod(int netId) {
Method connectMethod = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
//DebugUtils.printInfo(TAG, "connectWifiByReflectMethod road 1");
// 反射方法: connect(int, listener) , 4.2 <= phone‘s android version
for (Method methodSub : wifiManager.getClass().getDeclaredMethods()) {
if ("connect".equalsIgnoreCase(methodSub.getName())) {
Class<?>[] types = methodSub.getParameterTypes();
if (types != null && types.length > 0) {
if ("int".equalsIgnoreCase(types[0].getName())) {
connectMethod = methodSub;
}
}
}
}
if (connectMethod != null) {
try {
connectMethod.invoke(wifiManager, netId, null);
} catch (Exception e) {
e.printStackTrace();
//DebugUtils.printInfo(TAG, "connectWifiByReflectMethod Android "
// + Build.VERSION.SDK_INT + " error!");
return null;
}
}
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
// 反射方法: connect(Channel c, int networkId, ActionListener listener)
// 暂时不处理4.1的情况 , 4.1 == phone‘s android version
//DebugUtils.printInfo(TAG, "connectWifiByReflectMethod road 2");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
//DebugUtils.printInfo(TAG, "connectWifiByReflectMethod road 3");
// 反射方法:connectNetwork(int networkId) ,
// 4.0 <= phone‘s android version < 4.1
for (Method methodSub : wifiManager.getClass()
.getDeclaredMethods()) {
if ("connectNetwork".equalsIgnoreCase(methodSub.getName())) {
Class<?>[] types = methodSub.getParameterTypes();
if (types != null && types.length > 0) {
if ("int".equalsIgnoreCase(types[0].getName())) {
connectMethod = methodSub;
}
}
}
}
if (connectMethod != null) {
try {
connectMethod.invoke(wifiManager, netId);
} catch (Exception e) {
e.printStackTrace();
//DebugUtils.printInfo(TAG, "connectWifiByReflectMethod Android "
// + Build.VERSION.SDK_INT + " error!");
return null;
}
}
} else {
// < android 4.0
return null;
}
return connectMethod;
}
public String getCurrentWifiname() {
try {
if(wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED){ //wifi已经打开
WifiInfo info = wifiManager.getConnectionInfo();
String wifiId = info != null ? info.getSSID() : null;
//DebugUtils.printInfo("", "getCurrentWifiname wifiId: " + wifiId);
return wifiId;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
代码已经测试ok
整个项目源码