Android12 WIFI 无法提供互联网连接

平台

RK3588 + Android 12

问题描述

ConnectivityService是Android系统中负责处理网络连接的服务之一。它负责管理设备的网络连接状态,包括Wi-Fi、移动数据、蓝牙等。
在Android系统中,ConnectivityService提供了一些关键功能,包括但不限于:

  1. 网络状态监测: 它监测设备的网络状态,包括连接到的网络类型(如Wi-Fi、移动数据)、网络是否可用等。
  2. 网络类型切换: 当设备从一个网络切换到另一个网络时,ConnectivityService负责协调这个过程,以确保应用程序可以继续正常工作。
  3. 网络连接管理: 它允许应用程序查询当前网络连接的状态,并可以请求建立或中断网络连接。
  4. 网络通知: 它可以向应用程序发送广播通知,以通知它们有关网络状态的变化。

本文主要记录两点:

  1. Android 12 的ConnectivityService源码路径和机构的一些变化
  2. Wifi连接中的"已连接到设备,但无法提供互联网连接"问题.
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在连接到指定的WIFI热点后, 有时候会显示上面的提示信息, 大致的意思就是, 连上了但是上不了网

WIFI 设置

packages/apps/Settings/src/com/android/settings/network/NetworkProviderSettings.java

Can’t provide internet在哪里? 不在Settings 也不在 SettingsLib, 而是在WifiTrackerLib

frameworks/opt/net/wifi/libs/WifiTrackerLib/res/values/strings.xml

    <!-- Summary for connected wifi network without internet [CHAR LIMIT=NONE] -->
    <string name="wifitrackerlib_wifi_connected_cannot_provide_internet">
        Connected to device. Can\'t provide internet.</string>

frameworks/opt/net/wifi/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
wifitrackerlib_wifi_connected_cannot_provide_internet

    static String getCurrentNetworkCapabilitiesInformation(Context context,
            NetworkCapabilities networkCapabilities) {
        if (context == null || networkCapabilities == null) {
            return "";
        }

        if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)) {
            return context.getString(context.getResources()
                    .getIdentifier("network_available_sign_in", "string", "android"));
        }

        if (networkCapabilities.hasCapability(
                NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
            return context.getString(R.string.wifitrackerlib_wifi_limited_connection);
        }

        if (!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
            if (networkCapabilities.isPrivateDnsBroken()) {
                return context.getString(R.string.wifitrackerlib_private_dns_broken);
            }
            return context.getString(
                R.string.wifitrackerlib_wifi_connected_cannot_provide_internet);
        }
        return "";
    }

ConnectivityManager.java 有几个, 需要注意不要改错

frameworks/layoutlib/bridge/src/android/net/ConnectivityManager.java
packages/modules/Connectivity/core/java/android/net/ConnectivityManager.java
packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java

ConnectivityService.java 同样有多个

packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
packages/modules/Connectivity/services/core/java/com/android/server/ConnectivityService.java

如何单编译ConnectivityService 注意, 使用的是service.

mmm packages/modules/Connectivity/service/:service-connectivity
# 将会生成文件:
out/target/product/rk3588_s/system/apex/com.android.tethering/javalib/service-connectivity.jar

替换主板中的文件并重启即可

# 需注意,主板中有两个同名文件:
#	/apex/com.android.tethering/javalib/service-connectivity.jar
#	/system/apex/com.android.tethering.inprocess/javalib/service-connectivity.jar
# 不要搞错路径
## root 和 remount 之后
adb push service-connectivity.jar /system/apex/com.android.tethering.inprocess/javalib/

    在 Android 源代码中,com.android.tethering 通常用于处理网络共享(Tethering)的功能。网络共享允许设备通过不同的网络接口(如移动数据、Wi-Fi或蓝牙)与其他设备共享其网络连接。

具体来说,com.android.tethering 是 Android 框架的一部分,负责实现和管理网络共享的相关功能。这包括创建和管理 Wi-Fi 热点、USB 网络共享以及蓝牙网络共享等。

简单整理下Wifi列表中连接状态的数据传递:

NetworkProviderSettings WifiPickerTracker BaseWifiTracker ConnectivityManager CallbackHandler ConnectivityService NetworkStateTrackerHandler packages/apps/Settings getWifiEntries frameworks/opt/net/wifi/libs/WifiTrackerLib onStart packages/modules/Connectivity/service registerNetworkCallback sendRequestForNetwork trigger maybeHandleNetworkMonitorMessage handleNetworkTested updateCapabilities notifyNetworkCallbacks callCallbackForRequest handleMessage(CALLBACK_CAP_CHANGED) onCapabilitiesChanged handleNetworkCapabilitiesChanged NetworkProviderSettings WifiPickerTracker BaseWifiTracker ConnectivityManager CallbackHandler ConnectivityService NetworkStateTrackerHandler

修改

  1. 修改认证地址
    先看一段LOG:
PROBE_DNS www.google.cn 5055ms OK 220.181.174.226
PROBE_DNS www.google.cn 5059ms OK 220.181.174.226
PROBE_HTTP http://www.google.cn/generate_204 time=126ms ret=204 request={Connection=[close], User-Agent=[Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.32 Safari/537.36]} headers={null=[HTTP/1.1 204 No Content], Connection=[close], Content-Length=[0], Cross-Origin-Resource-Policy=[cross-origin], Date=[Tue, 05 Dec 2023 01:21:40 GMT], X-Android-Received-Millis=[1701739300483], X-Android-Response-Source=[NETWORK 204], X-Android-Selected-Protocol=[http/1.1], X-Android-Sent-Millis=[1701739300402]}
PROBE_HTTPS https://www.google.cn/generate_204 time=284ms ret=204 request={Connection=[close], User-Agent=[Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.32 Safari/537.36]} headers={null=[HTTP/1.1 204 No Content], Alt-Svc=[h3=":443"; ma=2592000,h3-29=":443"; ma=2592000], Connection=[close], Content-Length=[0], Cross-Origin-Resource-Policy=[cross-origin], Date=[Tue, 05 Dec 2023 01:21:40 GMT], X-Android-Received-Millis=[1701739300641], X-Android-Response-Source=[NETWORK 204], X-Android-Selected-Protocol=[http/1.1], X-Android-Sent-Millis=[1701739300521]}
PROBE_FALLBACK http://www.google.com/gen_204 Probe failed with exception java.net.ConnectException: Failed to connect to www.google.com/4.78.139.54:80
PROBE_FALLBACK http://www.google.com/gen_204 Probe failed with exception java.net.SocketTimeoutException: failed to connect to www.google.com/31.13.94.37 (port 80) from /192.168.1.86 (port 51118) after 10000ms

packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java

    @VisibleForTesting
    public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
            IpConnectivityLog logger, SharedLog validationLogs,
            @NonNull NetworkStackServiceManager serviceManager, Dependencies deps,
            @Nullable TcpSocketTracker tst) {
        // Add suffix indicating which NetworkMonitor we're talking about.
        super(TAG + "/" + network.toString());

        // ...
        mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled();
        mPrivateIpNoInternetEnabled = getIsPrivateIpNoInternetEnabled();
        mMetricsEnabled = deps.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY,
                NetworkStackUtils.VALIDATION_METRICS_VERSION, true /* defaultEnabled */);
        mUseHttps = getUseHttpsValidation();
        mCaptivePortalUserAgent = getCaptivePortalUserAgent();
        mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls();
		android.util.Log.d(TAG, "mCaptivePortalHttpsUrls[0]=" + mCaptivePortalHttpsUrls[0].toString());
        mCaptivePortalHttpUrls = makeCaptivePortalHttpUrls();
        mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls();
        mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs();
        //....
	}
    private URL[] makeCaptivePortalHttpsUrls() {
        final URL testUrl = getTestUrl(TEST_CAPTIVE_PORTAL_HTTPS_URL);
        if (testUrl != null) return new URL[] { testUrl };

        final String firstUrl = getCaptivePortalServerHttpsUrl();
        try {
            final URL[] settingProviderUrls =
                combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_HTTPS_URLS);
            // firstUrl will at least be default configuration, so default value in
            // getProbeUrlArrayConfig is actually never used.
            return getProbeUrlArrayConfig(settingProviderUrls,
                    R.array.config_captive_portal_https_urls,
                    DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS, this::makeURL);
        } catch (Exception e) {
            // Don't let a misconfiguration bootloop the system.
            Log.e(TAG, "Error parsing configured https URLs", e);
            // Ensure URL aligned with legacy configuration.
            return new URL[]{makeURL(firstUrl)};
        }
    }
    private String getCaptivePortalServerHttpsUrl() {
        return getSettingFromResource(mCustomizedContext,
                R.string.config_captive_portal_https_url, CAPTIVE_PORTAL_HTTPS_URL,
                mCustomizedContext.getResources().getString(
                R.string.default_captive_portal_https_url));
    }

修改配置文件即可:

packages/modules/NetworkStack/res/values/config.xml

<!-- HTTP URL for network validation, to use for detecting captive portals. -->
    <!-- default_captive_portal_http_url is not configured as overlayable so
         OEMs that wish to change captive_portal_http_url configuration must
         do so via configuring runtime resource overlay to
         config_captive_portal_http_url and *NOT* by changing or overlaying
         this resource. It will break if the enforcement of overlayable starts.
         -->
    <string name="default_captive_portal_http_url" translatable="false">http://connectivitycheck.gstatic.com/generate_204</string>
    <!-- HTTPS URL for network validation, to use for confirming internet connectivity. -->
    <!-- default_captive_portal_https_url is not configured as overlayable so
         OEMs that wish to change captive_portal_https_url configuration must
         do so via configuring runtime resource overlay to
         config_captive_portal_https_url and *NOT* by changing or overlaying
         this resource. It will break if the enforcement of overlayable starts.
         -->
    <string name="default_captive_portal_https_url" translatable="false">https://www.google.com/generate_204</string>

    <!-- List of fallback URLs to use for detecting captive portals. -->
    <!-- default_captive_portal_fallback_urls is not configured as overlayable
         so OEMs that wish to change captive_portal_fallback_urls configuration
         must do so via configuring runtime resource overlay to
         config_captive_portal_fallback_urls and *NOT* by changing or overlaying
         this resource. It will break if the enforcement of overlayable starts.
         -->
    <string-array name="default_captive_portal_fallback_urls" translatable="false">
        <item>http://www.google.com/gen_204</item>
        <item>http://play.googleapis.com/generate_204</item>
    </string-array>
    <!-- Configuration hooks for the above settings.
         Empty by default but may be overridden by RROs. -->
    <integer name="config_captive_portal_dns_probe_timeout"></integer>
    <!--suppress CheckTagEmptyBody: overlayable resource to use as configuration hook -->
    <string name="config_captive_portal_http_url" translatable="false"></string>
    <!--suppress CheckTagEmptyBody: overlayable resource to use as configuration hook -->
    <string name="config_captive_portal_https_url" translatable="false"></string>

前面改了不生效, 注意:OVERLAY

device/rockchip/common/overlay/packages/modules/NetworkStack/res/values/config.xml

<string name="config_captive_portal_http_url" translatable="false">http://www.google.cn/generate_204</string>

编译:mmm packages/modules/NetworkStack/:InProcessNetworkStack

还可以尝试使用RRO的方式

vendor/rockchip/common/gms/RockchipNetworkStackConfigOverlay/res/values/config.xml

<string name="config_captive_portal_https_url" translatable="false">https://www.google.cn/generate_204</string>
  1. 自动确认保持连接
    通知的发出:
showNotification tag=ConnectivityNotification:100 event=NO_INTERNET transport=WLAN name=XXXX highPriority=true
 private void showNetworkNotification(NetworkAgentInfo nai, NotificationType type) {
        final String action;
        final boolean highPriority;
        switch (type) {
            case NO_INTERNET:
                action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
                // High priority because it is only displayed for explicitly selected networks.
                highPriority = true;
                break;
            case PRIVATE_DNS_BROKEN:
                action = Settings.ACTION_WIRELESS_SETTINGS;
                // High priority because we should let user know why there is no internet.
                highPriority = true;
                break;
            case LOST_INTERNET:
                action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
                // High priority because it could help the user avoid unexpected data usage.
                highPriority = true;
                break;
            case PARTIAL_CONNECTIVITY:
                action = ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY;
                // Don't bother the user with a high-priority notification if the network was not
                // explicitly selected by the user.
                highPriority = nai.networkAgentConfig.explicitlySelected;
                break;
            default:
                Log.wtf(TAG, "Unknown notification type " + type);
                return;
        }

        Intent intent = new Intent(action);
        if (type != NotificationType.PRIVATE_DNS_BROKEN) {
            intent.putExtra(ConnectivityManager.EXTRA_NETWORK, nai.network);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            // Some OEMs have their own Settings package. Thus, need to get the current using
            // Settings package name instead of just use default name "com.android.settings".
            final String settingsPkgName = getSettingsPackageName(mContext.getPackageManager());
            intent.setClassName(settingsPkgName,
                    settingsPkgName + ".wifi.WifiNoInternetDialog");
        }

        PendingIntent pendingIntent = PendingIntent.getActivity(
                mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
                0 /* requestCode */,
                intent,
                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);

        mNotifier.showNotification(
                nai.network.getNetId(), type, nai, null, pendingIntent, highPriority);
    }

点击通知后:

START u0 {act=android.net.action.PROMPT_UNVALIDATED flg=0x10000000 cmp=com.android.settings/.wifi.WifiNoInternetDialog (has extras)} from uid 1000

看Settings的清单:

packages/apps/Settings/AndroidManifest.xml

        <activity android:name=".wifi.WifiNoInternetDialog"
                  android:clearTaskOnLaunch="true"
                  android:excludeFromRecents="true"
                  android:exported="true"
                  android:permission="android.permission.NETWORK_STACK"
                  android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight">
            <!-- TODO: Consider removing below two intent filters.
                 It seems like below two intent filters can be removed because when the notification
                 is clicked, this activity will be launched anyway. -->
            <intent-filter>
                <action android:name="android.net.action.PROMPT_UNVALIDATED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.net.action.PROMPT_LOST_VALIDATION" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                android:value="true" />
        </activity>

packages/apps/Settings/src/com/android/settings/wifi/WifiNoInternetDialog.java

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (which != BUTTON_NEGATIVE && which != BUTTON_POSITIVE) return;
        final boolean always = mAlwaysAllow.isChecked();
        final String what, action;

        mButtonClicked = true;

        if (ACTION_PROMPT_UNVALIDATED.equals(mAction)) {
            what = "NO_INTERNET";
            final boolean accept = (which == BUTTON_POSITIVE);
            action = (accept ? "Connect" : "Ignore");
            mCM.setAcceptUnvalidated(mNetwork, accept, always);
        } else if (ACTION_PROMPT_PARTIAL_CONNECTIVITY.equals(mAction)) {
            what = "PARTIAL_CONNECTIVITY";
            final boolean accept = (which == BUTTON_POSITIVE);
            action = (accept ? "Connect" : "Ignore");
            mCM.setAcceptPartialConnectivity(mNetwork, accept, always);
        } else {
            what = "LOST_INTERNET";
            final boolean avoid = (which == BUTTON_POSITIVE);
            action = (avoid ? "Switch away" : "Get stuck");
            if (always) {
                Settings.Global.putString(mAlertParams.mContext.getContentResolver(),
                        Settings.Global.NETWORK_AVOID_BAD_WIFI, avoid ? "1" : "0");
            } else if (avoid) {
                mCM.setAvoidUnvalidated(mNetwork);
            }
        }
        Log.d(TAG, what + ": " + action +  " network=" + mNetwork +
                (always ? " and remember" : ""));
    }

packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java

    @Override
    public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
        enforceNetworkStackSettingsOrSetup();
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_UNVALIDATED,
                encodeBool(accept), encodeBool(always), network));
    }
    
    private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
        if (DBG) log("handleSetAcceptUnvalidated network=" + network +
                " accept=" + accept + " always=" + always);

        NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
        if (nai == null) {
            // Nothing to do.
            return;
        }

        if (nai.everValidated) {
            // The network validated while the dialog box was up. Take no action.
            return;
        }

        if (!nai.networkAgentConfig.explicitlySelected) {
            Log.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
        }

        if (accept != nai.networkAgentConfig.acceptUnvalidated) {
            nai.networkAgentConfig.acceptUnvalidated = accept;
            // If network becomes partial connectivity and user already accepted to use this
            // network, we should respect the user's option and don't need to popup the
            // PARTIAL_CONNECTIVITY notification to user again.
            nai.networkAgentConfig.acceptPartialConnectivity = accept;
            nai.updateScoreForNetworkAgentUpdate();
            rematchAllNetworksAndRequests();
        }

        if (always) {
            nai.onSaveAcceptUnvalidated(accept);
        }

        if (!accept) {
            // Tell the NetworkAgent to not automatically reconnect to the network.
            nai.onPreventAutomaticReconnect();
            // Teardown the network.
            teardownUnneededNetwork(nai);
        }

    }

增加属性控制, 不发送通知, 并执行保持连接:

    private void handlePromptUnvalidated(Network network) {
		//Force keep-connect for network
		if("1".equals(android.os.SystemProperties.get("persist.sys.keepNetworkConnect"))){
			handleSetAcceptUnvalidated(network, true, true);
			return;
		}
	}

参考

ConnectivityService处理wifi连接
android 网络连接受限解决
android 网络重新连接时BaseActivity处理 android网络连接受限
android wif 去掉 双引号 原生安卓去掉wifi叉号
AndroidQ RRO(Runtime Resource Overlay)机制(1)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/219623.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RocketMQ详解

目录 1、RocketMQ 介绍1.1、RocketMQ 特点1.2 RocketMQ优势 2 RocketMQ基本概念2.1 NameServer2.1.1 NameServer作用2.1.2 高可用保障 2.2 Broker2.2.1 部署方式2.2.1.1 单 Master2.2.1.2 多 Master2.2.1.3 多 Master 多 Slave&#xff08;异步复制&#xff09;2.2.1.4 多 Mast…

高压放大器研究方向及其应用领域

高压放大器是一种电子设备&#xff0c;用于将输入信号的电压增大到较高的输出电压。它在许多领域中有广泛的应用&#xff0c;包括通信、医疗、科学研究等。 高压放大器的研究方向主要集中在以下几个方面&#xff1a; 提高功率效率&#xff1a;高压放大器需要能够提供足够的输出…

外贸建站要国外服务器吗?海外服务器推荐?

外贸建站如何选国外服务器&#xff1f;海洋建站用什么服务器好&#xff1f; 外贸建站已经成为企业拓展国际市场的一项重要举措。然而&#xff0c;一个关键问题摆在许多企业面前&#xff1a;外贸建站是否需要选择国外服务器呢&#xff1f;这个问题涉及到多方面的考虑因素&#…

RAR文件的密码保护如何设置和取消?

RAR文件是压缩包一种常用的压缩文件格式&#xff0c;对于这种文件&#xff0c;我们如何设置和取消密码保护呢&#xff1f; 首先我们要下载适用于RAR文件的WinRAR解压缩软件&#xff0c;然后在压缩文件的时候&#xff0c;就可以同步设置密码&#xff0c;选中需要压缩的文件&…

【@ConfigurationProperties注解的用处】

介绍 ConfigurationProperties 是 Spring 框架中的一个注解&#xff0c;用于将配置文件中的属性映射到 Java 对象的字段上。它的主要用途是简化配置文件与 Java 对象之间的映射过程&#xff0c;使得配置更加方便、可读&#xff0c;并提供类型安全的属性访问。 用途和特性 属性…

云计算与低代码:加速应用开发与创新的双核引擎

云计算与低代码是当前技术领域中备受关注的两大趋势。本文将探讨云计算与低代码的定义、应用领域以及它们如何协同作用&#xff0c;加速应用开发与创新的进程。 引言 随着科技的飞速发展&#xff0c;数字化转型已经成为了企业追求高效和创新的重要途径。在这个过程中&#xff0…

推荐一款优秀的json在线格式化校验工具

www.bjson.chat 这个工具是目前见过最好用的JSON工具&#xff0c; 页面简单&#xff0c;支持text&#xff0c;tree两种显示格式&#xff0c;关键词高亮显示支持亮白和暗黑两种风格最主要的是如果要格式化很长的json的话&#xff0c;这个工具还可以全屏显示&#xff0c;简直不…

【图论】重庆大学图论与应用课程期末复习资料2-各章考点(计算部分)(私人复习资料)

图论各章考点 二、树1、避圈法&#xff08;克鲁斯克尔算法&#xff09;2、破圈法3、Prim算法 四、路径算法1、Dijkstra算法2、Floyd算法 五、匹配1、匈牙利算法&#xff08;最大权理想匹配&#xff08;最小权权值取反&#xff09;&#xff09; 六、行遍性问题1、Fleury算法&…

Spring系列注解补充

JsonProperty JsonProperty 是jackson-databindjar包提供的注解&#xff0c;用于实体类的属性上&#xff0c;功能是把属性名称转换为另一个名称&#xff08;即 两个名称都指向同一个变量值&#xff09; 该注解主要用于实体类的属性上&#xff0c;作用可以简单的理解为在反序列…

前端依赖下载速度过慢解决方法,nrm 镜像管理工具

npm 默认镜像 &#xff1a;https://registry.npmjs.org/ 问题 使用 npm install 安装依赖的时候&#xff0c;受网络的限制&#xff0c;速度会很慢。 解决 使用国内镜像代理。 nrm nrm 是镜像源管理工具&#xff1b; 1. 安装 nrm npm install nrm --global# 查看镜像源列…

金蝶云星空对接泛微E9流程打通示例

泛微E9对接金蝶云星空&#xff0c;主要介绍由泛微OA发起审批后把审批结果和审批意见回传给到金蝶云星空财务进行做账处理。实现内部办公一体化&#xff08;使用案例场景&#xff1a;报销申请&#xff0c;付款申请等&#xff09;。 数据源系统&#xff1a;泛微OA-E9 泛微OA&…

搜维尔科技:AI时代,迈向2030元宇宙数字人戏曲教育数字化思维、战略与未来!

一场关于中国传统戏曲与数字媒体交汇的探讨之旅将于今日在清华大学开讲&#xff0c;本次活动旨在推动AI时代大背景下&#xff0c;利用元宇宙、数字人等创新技术焕发中国传统戏曲全新活力。 讲座以“AI时代&#xff0c;迈向2030元宇宙数字人戏曲教育数字化思维、战略与未来”为主…

「词令」2023年12月5日支付宝蚂蚁庄园今日问题答案是什么?12.5蚂蚁庄园今日问题正确答案

问题&#xff1a;我国哪个城市有“四面荷花三面柳&#xff0c;一城山色半城湖”的美誉&#xff1f; 选项&#xff1a;A、济南 B、泉州 答案&#xff1a;济南 解析&#xff1a;一城山色&#xff1a;千佛山在城南&#xff0c;为附近最高的山&#xff0c;全城人都能看到它苍翠的…

Docker镜像构建:技术深度解析与实践

目录 ​编辑 一、Docker镜像基础与优化 Docker镜像概念 Dockerfile详解 层级缓存机制 二、镜像构建的高级技术 多阶段构建 安全性考量 三、构建性能优化与调试 性能优化策略 构建过程调试 四、代码实战 实例&#xff1a;构建优化的Docker镜像 调试技巧 实例&…

敏捷开发迭代缺陷统计的重要性

在敏捷开发中&#xff0c;迭代缺陷统计具有重要性&#xff0c;对团队和项目具有多方面的影响&#xff1a; 早期发现和解决问题&#xff1a; 迭代缺陷统计允许团队及时识别和定位在迭代中出现的问题。这有助于早期解决问题&#xff0c;避免问题扩大化&#xff0c;并最大程度地减…

Java Websocket实现即时通讯功能入门教程

近年来&#xff0c;即时通讯&#xff08;Instant Messaging&#xff09;已经成为了人们日常生活中不可缺少的一部分。而Java Websocket技术则提供了一种简便高效的方式来实现即时通讯功能。本文将介绍如何使用Java Websocket来实现即时通讯&#xff0c;并提供具体的代码示例。 …

【C语言】分支语句详解

目录 一、C语言语句类型 1.语句是什么 2.C语言的五类语句 二、分支语句 1. if语句 a. if语句的基本语法结构 b.悬空else 2.switch语句 a.switch语句的语法形式 b.default语句 一、C语言语句类型 1.语句是什么 在C语言中&#xff0c;语句是以分号结尾的字符序列&#…

陀螺仪防抖术语

陀螺仪防抖术语 fov 视场角 drift 零偏   MotionFusion即运动传感器的融合补偿&#xff0c;对陀螺仪、加速度计等运动测量器件的数据 进行预处理&#xff0c;通过标定和补偿&#xff0c;为防抖提供校准后的陀螺仪数据 ratio 系数 gyro 陀螺仪 calibration 校准 标定 DIS&…

开发与AI的邂逅

目录 一、前言 二、百度文心一言 三、阿里通义灵码 3.1.工具介绍 3.2.产品功能 3.3.配置流程 3.4.适用范围 3.5.收费标准 3.6.注意事项 一、前言 前段时间&#xff0c;由OpenAI公司研发的一款聊天机器人程序ChatGPT&#xff08;全名&#xff1a;Chat Generative …

CLIP在Github上的使用教程

CLIP的github链接&#xff1a;https://github.com/openai/CLIP CLIP Blog&#xff0c;Paper&#xff0c;Model Card&#xff0c;Colab CLIP&#xff08;对比语言-图像预训练&#xff09;是一个在各种&#xff08;图像、文本&#xff09;对上进行训练的神经网络。可以用自然语…