周记1

1.  Android studio grade配置relesase/debug版本的签名文件,需要放在defaultConfig和buildTypes 之前

signingConfigs {
        release {
            keyAlias 'xierapp'
            keyPassword 'xierandroid123'
            storeFile file('release.jks')
            storePassword 'xierandroid123'
        }

        debug {
            keyAlias 'xierapp'
            keyPassword 'xierandroid123'
            storeFile file('release.jks')
            storePassword 'xierandroid123'
        }
    }

2. jni了解

第一步先在类中创建javanative 方法

public static native String getStringFromNDK();

第二步build make project. 然后就能在build中找到这些文件

第三步在命令行切换到debug目录 执行 javah -classpath . -jni 你的native方法所在类的路径,生成.h文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_scy_android_ndkdemo_NDKTools */

#ifndef _Included_com_scy_android_ndkdemo_NDKTools
#define _Included_com_scy_android_ndkdemo_NDKTools
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_scy_android_ndkdemo_NDKTools
 * Method:    getStringFromNDK
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_scy_android_ndkdemo_NDKTools_getStringFromNDK
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

第四部创建jni 文件夹 把生成的.h文件放进来,再创建Android.mk 文件 和一个随意取名(我这里是ndkdemotest)的.c 文件

Android.mk

LOCAL_PATH := $(call my-dir)//$(call my-dir)调用NDK内部的函数获得当前.mk文件的路径

include $(CLEAR_VARS) //清空了除了LOCAL_PATH之外的所有LOCAL_xxx变量的值

LOCAL_MODULE    := ndkdemotest-jni//表示Android.mk中的每一个模块。名字必须唯一且不包含空格。

LOCAL_SRC_FILES := ndkdemotest.c//必须包含将要打包如模块的C/C++ 源码

include $(BUILD_SHARED_LIBRARY)//编译为动态库 

ndkdemotest.c (注意要引入你自己的.h文件)

#include "com_scy_android_ndkdemo_NDKTools.h"

JNIEXPORT jstring JNICALL Java_com_scy_android_ndkdemo_NDKTools_getStringFromNDK
        (JNIEnv *env, jobject obj) {
    return (*env)->NewStringUTF(env, "scy jni blog article");
}

最后配置buidl.grade 再在native方法里引入

//AndroidStudio 指定引入jniLibs的特定CPU架构的so库文件
ndk{
            moduleName "ndkdemotest-jni"
            abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
        }
    }
buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
//cmake 工具编译选项
        externalNativeBuild {
            ndkBuild {
                path 'src/main/jni/Android.mk'
            }
        }
        sourceSets.main {
            jni.srcDirs = []
      
        }
}


//在包含native的Java方法类中引入代码
static {
        System.loadLibrary("ndkdemotest-jni");
    }

3. 在jni 的基础之上开始了解串口通信

在调用native方法上与jni相似的,官方提供了两个打开和关闭串口的c方法,我们只需要调用即可,别忘记加上一些引入和配置。

// JNI(调用java本地接口,实现串口的打开和关闭)
    private native static FileDescriptor open(String path, int baudrate, int flags);
    public native void close();

//构造器供外部调用开启串口
public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {

        //检查访问权限,如果没有读写权限,进行文件操作,修改文件访问权限
//        if (!device.canRead() || !device.canWrite()) {
//
//            try {
//                //通过挂载到linux的方式,修改文件的操作权限
//                Process su = Runtime.getRuntime().exec("/system/xbin/su");
//                String cmd = "chmod 777 " + device.getAbsolutePath() + "\n" + "exit\n";
//                su.getOutputStream().write(cmd.getBytes());
//
//                if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
//                    Log.e("SerialPort", "SerialPort: 没有权限");
//                    throw new SecurityException();
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//                throw new SecurityException();
//            }
//        }

        mFd = open(device.getAbsolutePath(), baudrate, flags);

        if (mFd == null) {
            Log.e(TAG, "native open returns null");
            throw new IOException();
        }

        mFileInputStream = new FileInputStream(mFd);
        mFileOutputStream = new FileOutputStream(mFd);
    }

接下来就是一个封装的SerialPortUtil类了

public SerialPort openSerialPort(String path,int baudrate){
        try {
                serialPort = new SerialPort(new File(path),baudrate,0);// TODO: 2019/7/28  打开串口异常,path需修改,流报空指针
                this.serialPortStatus = true;
                threadStatus = false; //线程状态

                //获取打开的串口中的输入输出流,以便于串口数据的收发
                inputStream = serialPort.getInputStream();
                outputStream = serialPort.getOutputStream();

                new ReadThread().start(); //开始线程监控是否有数据要接收
        } catch (IOException e) {
            Log.d(TAG, "openSerialPort: 打开串口异常:" + e.toString());
            return serialPort;
        }
        Log.d(TAG, "openSerialPort: 打开串口");
        return serialPort;
    }

    /**
     * 关闭串口
     */
    public void closeSerialPort(){
        try {
            inputStream.close();
            outputStream.close();

            this.serialPortStatus = false;
            this.threadStatus = true; //线程状态
            serialPort.close();
        } catch (IOException e) {
            Log.e(TAG, "closeSerialPort: 关闭串口异常:"+e.toString());
            return;
        }
        Log.d(TAG, "closeSerialPort: 关闭串口成功");
    }

    /**
     * 发送串口指令(字符串)
     * @param data String数据指令
     */
    public void sendSerialPort(String data){
        Log.d(TAG, "sendSerialPort: 发送数据");

        try {
            byte[] sendData = data.getBytes(); //string转byte[]
            this.data_ = new String(sendData); //byte[]转string
            if (sendData.length > 0) {
                outputStream.write(sendData);
                outputStream.write('\n');
                //outputStream.write('\r'+'\n');
                outputStream.flush();
                Log.d(TAG, "sendSerialPort: 串口数据发送成功");
            }
        } catch (IOException e) {
            Log.e(TAG, "sendSerialPort: 串口数据发送失败:"+e.toString());
        }

    }

    /**
     * 单开一线程,来读数据
     */
    private class ReadThread extends Thread{
        @Override
        public void run() {
            super.run();
            //判断进程是否在运行,更安全的结束进程
            while (!threadStatus){
                Log.d(TAG, "进入线程run");
                //64   1024
                byte[] buffer = new byte[64];
                int size; //读取数据的大小
                try {
                    size = inputStream.read(buffer);
                    if (size > 0){
                        Log.d(TAG, "run: 接收到了数据:" + changeTool.ByteArrToHex(buffer));
                        Log.d(TAG, "run: 接收到了数据大小:" + String.valueOf(size));
                        //提供回调接口,告知调用方收到了信息
                        onDataReceiveListener.onDataReceive(buffer,size);
                    }
                } catch (IOException e) {
                    Log.e(TAG, "run: 数据读取异常:" +e.toString());
                }
            }

        }
    }

4. 学习Android  wifi 开发

SSID 网络名字

RSSID/level wifi信号强度

capabilities wifi的加密类型

BSSID wifi的物理地址

加入权限,动态申请ACCESS_FINE_LOCATION,提示打开GPS。

<uses-permission android:name="android.permission.CHANGE_NETWORK_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.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

//检查GPS是否开启
private boolean checkGpsIsOpen() {
        boolean isOpen;
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        isOpen = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        return isOpen;
}
//未开启则请求跳转GPS开启界面
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, Constants.LOCATION_REQUEST_2);

获取WifiManager对象

mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);

判断当前wifi是否开启

if (!mWifiManager.isWifiEnabled()) {
       mWifiManager.setWifiEnabled(true);
   }

判断wifi是否保存

/**
     * descirption: 判断wifi是否已保存
     */
    public static WifiConfiguration isWifiSave(String SSID) {
        if (mWifiConfigurations != null) {
            for (WifiConfiguration existingConfig : mWifiConfigurations) {
                if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
                    return existingConfig;
                }
            }
        }
        return null;
    }

注册广播接收wifi的一些信息再继续做操作

//注册广播
    public void initReceiver() {
        wifiBroadCastReceiver = new WifiBroadCastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        if (wifiBroadCastReceiver != null) {
            registerReceiver(wifiBroadCastReceiver, filter);
        }
    }

class WifiBroadCastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                //当扫描到结果后
                if (loadingLl.getVisibility() == View.VISIBLE) {
                    loadingLl.setVisibility(View.GONE);
                }
                initRecyclerView();
            } else if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                //wifi连接网络状态
                NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                NetworkInfo.DetailedState state = info.getDetailedState();
                if (state == state.SCANNING) {
                    ToastUtils.showShort("正在扫描");
                } else if (state == state.AUTHENTICATING) {
                    ToastUtils.showShort("正在验证身份信息");
                } else if (state == state.OBTAINING_IPADDR) {
                    ToastUtils.showShort("正在获取IP地址");
                } else if (state == state.CONNECTING) {
                    ToastUtils.showShort("正在连接");
                } else if (state == state.CONNECTED) {
                    ToastUtils.showShort("建立连接");
                    if (adapter != null) {
                        adapter.notifyDataSetChanged();
                    }
                } else if (state == state.DISCONNECTING) {
                    ToastUtils.showShort("正在断开连接");
                } else if (state == state.DISCONNECTED) {
                    ToastUtils.showShort("已断开连接");
                    if (adapter != null) {
                        adapter.notifyDataSetChanged();
                    }
                } else if (state == state.FAILED) {
                    ToastUtils.showShort("连接失败");
                    if (adapter != null) {
                        adapter.notifyDataSetChanged();
                    }
                }
            } else if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                这个监听wifi的打开与关闭,与wifi的连接无关
                int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1);
                switch (wifiState) {
                    case WifiManager.WIFI_STATE_DISABLED:
                        Log.d("WIFI状态", "wifiState:WIFI_STATE_DISABLED");
                        break;
                    case WifiManager.WIFI_STATE_DISABLING:
                        Log.d("WIFI状态", "wifiState:WIFI_STATE_DISABLING");
                        break;
                    case WifiManager.WIFI_STATE_ENABLED:
                        Log.d("WIFI状态", "wifiState:WIFI_STATE_ENABLED");
                        //监听到WIFI 已经开启,开始扫描
                        netSettingSwitch.setChecked(true);
                        results = WifiUtil.getScanResult(mWifiManager);
                        mWifiConfigurations = mWifiManager.getConfiguredNetworks();
                        loadingLl.setVisibility(View.VISIBLE);
                        break;
                    case WifiManager.WIFI_STATE_ENABLING:
                        Log.d("WIFI状态", "wifiState:WIFI_STATE_ENABLING");
                        ToastUtils.showShort("正在打开wifi...");
                        break;
                    case WifiManager.WIFI_STATE_UNKNOWN:
                        Log.d("WIFI状态", "wifiState:WIFI_STATE_UNKNOWN");
                        break;
                }
            } else if (intent.getAction().equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
                SupplicantState state = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
                int error = intent.getIntExtra(EXTRA_SUPPLICANT_ERROR, 0);
                if (error == WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE) {
                    ToastUtils.showShort("密码有误");
                }
            }
        }
    }

扫描wifi

mWifiManager.startScan();
List<ScanResult> results = mWifiManager.getScanResults();

获取当前Wifi的信息

/**
     * descirption: 获取当前连接wifi名字 内存溢出?
     */
    public static String getCurrentWifiSSID(Context context) {
        wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo info = wifiManager.getConnectionInfo();
        return info != null ? info.getSSID() : "null";
    }

连接WIfi,先根据传入的自定义对象保存的名字,密码,加密类型创建WifiConfiguration对象,再连接。

/**
     * descirption: 创建要连接的WifiConfiguration
     */
    public WifiConfiguration createConfiguration(AccessPoint ap) {
        String SSID = ap.getSsid();
        String password = ap.getPassword();
        String encryptionType = ap.getEncryptionType();
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.SSID = "\"" + SSID + "\"";
        //判断当前连接的wifi保存了密码,清除wifi保存信息
        WifiConfiguration tempConfig = isWifiSave(SSID);
        if (tempConfig != null) {
            mWifiManager.removeNetwork(tempConfig.networkId);
            mWifiManager.saveConfiguration();
            Log.d(TAG, "createConfiguration: 清除wifi保存信息");
        }
        if (encryptionType.contains("WEP")) {
            Log.d(TAG, "createConfiguration: wep");
            /**
             * special handling according to password length is a must for wep
             */
            int i = password.length();
            if (((i == 10 || (i == 26) || (i == 58))) && (password.matches("[0-9A-Fa-f]*"))) {
                config.wepKeys[0] = password;
            } else {
                config.wepKeys[0] = "\"" + 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 (encryptionType.contains("WPA")) {
            Log.d(TAG, "createConfiguration: 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.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            config.status = WifiConfiguration.Status.ENABLED;
        } else {
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        }
        return config;
    }

//去连接
AccessPoint accessPoint = new AccessPoint(results.get(position).SSID, results.get(position).capabilities, et.getText().toString());
                        WifiConfiguration wifiConfiguration = createConfiguration(accessPoint);
//如果你设置的wifi是设备已经存储过的,那么这个networkId会返回小于0的值。
int networkId = mWifiManager.addNetwork(wifiConfiguration);
                       
mWifiManager.enableNetwork(networkId, true);

注意点

WIfi开启需要时间,没有等到Wifi完全开启,立即去获取扫描列表是获取不到的。

Wifi扫描的列表会有重复和空的情况,需要处理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值