Android系统WIFI显示已保存但不会自动重连

问题描述

使用Android设备,已经连接过的WIFI不会自动重连,且显示已保存

问题分析

显示已保存说明连接的WIFI信息已经保存,Android 11连接的WIFI信息保存在该文件/data/misc/apexdata/com.android/wifi/WifiConfigStore.xml,查看发现不能自动重连的WIFI会有NETWORK_SELECTION_PERMANENTLY_DISABLED此项配置,正常的为NETWORK_SELECTION_ENABLED

<string name="SelectionStatus">NETWORK_SELECTION_PERMANENTLY_DISABLED</string>
<string name="DisableReason">NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT</string>

正常的:

<string name="SelectionStatus">NETWORK_SELECTION_ENABLED</string>
<string name="DisableReason">NETWORK_SELECTION_ENABLE</string>

经分析:此版本的WIFI由于没有通过校验会显示网络连接受限,导致保存连接的WiFi的信息有此配置,所以不会自动连接,只要解决显示网络连接受限的问题,即修改HTTPS校验网址可解决WIFI不自动重连的问题。

相关源码

保存的WIFI信息文件示例
frameworks/base/wifi/java/android/net/wifi/migration_samples/

WIFI信息保存路径
AOSP Path in Android 10: /data/misc/wifi/WifiConfigStore.xml
AOSP Path in Android 11: /data/misc/apexdata/com.android/wifi/WifiConfigStore.xml

自动连接机制
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiConnectivityManager.java
网络评估:handleScanResults
是否网络选择:isNetworkSelectionNeeded
扫描结果评估:SavedNetworkEvaluator

WIFI保存
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiConfigStore.java
关键方法:
loadFromStore()
createFile()
read()
write()
StoreData()

拓展

网上查到的关于断电时WIFI学习未来得及保存下来时,一般WIFI信息的保存是在空闲时间,一般不会立即写入flash中,也会导致不自动重连,解决方案是加个sync

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

private void  fileSync(){
    Runtime runtime = Runtime.getRuntime();
    try {
       runtime.exec("sync");
    } catch (IOException e) {
        e.printStackTrace();
            Log.e(TAG, "fileSync"); 
}

public boolean saveConfig() {
     boolean ret;
     ret = doBooleanCommand("SAVE_CONFIG");
     //add fileSync
     fileSync();
     return ret;
}
要在Qt for Android中调用原生系统摄像头进行录像并保存输出,可以使用Android NDK来实现。下面是实现步骤: 1. 在Qt项目中添加一个Java文件,文件名为CameraRecorder.java,代码如下: ``` package com.example.myapplication; import android.hardware.Camera; import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.os.Environment; import android.util.Log; import android.view.SurfaceHolder; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; public class CameraRecorder implements SurfaceHolder.Callback { private static final String TAG = "CameraRecorder"; private Camera mCamera; private MediaRecorder mMediaRecorder; private SurfaceHolder mHolder; private boolean mIsRecording = false; public CameraRecorder(SurfaceHolder holder) { mHolder = holder; mHolder.addCallback(this); } public void startRecording() { if (mCamera == null) { mCamera = getCameraInstance(); } try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (IOException e) { Log.e(TAG, "Error starting camera preview: " + e.getMessage()); } mMediaRecorder = new MediaRecorder(); mCamera.unlock(); mMediaRecorder.setCamera(mCamera); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); mMediaRecorder.setProfile(profile); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); String currentDateAndTime = dateFormat.format(new Date()); File mediaFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Camera/", "VID_" + currentDateAndTime + ".mp4"); mMediaRecorder.setOutputFile(mediaFile.getAbsolutePath()); try { mMediaRecorder.prepare(); } catch (IOException e) { Log.e(TAG, "Error preparing media recorder: " + e.getMessage()); } mMediaRecorder.start(); mIsRecording = true; } public void stopRecording() { if (mIsRecording) { mMediaRecorder.stop(); mMediaRecorder.release(); mCamera.lock(); mCamera.release(); mCamera = null; mIsRecording = false; } } private Camera getCameraInstance() { Camera camera = null; try { camera = Camera.open(); } catch (Exception e) { Log.e(TAG, "Error opening camera: " + e.getMessage()); } if (camera != null) { Camera.Parameters params = camera.getParameters(); List<Camera.Size> sizes = params.getSupportedPreviewSizes(); Camera.Size size = sizes.get(0); params.setPreviewSize(size.width, size.height); camera.setParameters(params); } return camera; } @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { stopRecording(); } } ``` 2. 在Qt项目的AndroidManifest.xml文件中添加如下权限: ``` <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ``` 3. 在Qt项目中添加一个QML页面,页面中添加一个SurfaceView控件,并在控件上叠加一个按钮,代码如下: ``` import QtQuick 2.0 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.2 import QtQuick.Dialogs 1.2 import QtAndroidExtras 1.4 Rectangle { id: root width: 360 height: 640 color: "white" SurfaceView { id: surfaceView anchors.fill: parent } Button { id: btnRecorder text: "Start Recording" width: 200 height: 50 anchors.centerIn: parent onClicked: { if (btnRecorder.text === "Start Recording") { var recorder = QtAndroid.createQmlObject('import com.example.myapplication 1.0; CameraRecorder {id: recorder;}', surfaceView); recorder.startRecording(); btnRecorder.text = "Stop Recording"; } else { recorder.stopRecording(); btnRecorder.text = "Start Recording"; } } } } ``` 4. 编译并运行Qt项目,在页面中点击按钮即可开始录制视频。视频文件保存在SD卡的DCIM/Camera目录下。 以上代码仅为示例代码,具体实现可以根据自己的需求进行修改。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值