Android 检查网络状态和监听网络状态变化

news2024/11/24 1:51:14

此篇存在的主要意义在于解决用户使用app中网络状态发生了变化,需要我们去动态监听网络连接状态(有网、无网)、网络类型 (包括wifi、移动网络 -> 3G、4G等等)

在这里插入图片描述

文章目录

        • 门前授课
        • 具体实现
        • 异常场景
        • 兴趣扩展

门前授课

关于网络状态的监听,主要是基于 Android 广播 - BroadcaseReceiver组件
~

同时关于广播的注册方面,从Android7.0开始已经初步进行限制,所以尽可能采用动态注册,献文如下:

Apps targeting Android 7.0 (API level 24) and higher do not receive this
broadcast if they declare the broadcast receiver in their manifest. Apps
will still receive broadcasts if they register their BroadcastReceiver with
Context.registerReceiver() and that context is still valid.
直译如下
针对Android 7.0
(API级别24)或更高的应用程序,如果它们在其manifest中声明广播接收器,则不会接收此广播。如果应用程序将其BroadcastReceiver注册为context
. registerreceiver()并且该context仍然有效,那么应用程序仍然会接收广播

Google在Android7.0时虽已对广播添加了限制,但是Android8.0后基于安全原因又一次加强了限制,且已声明:
应用无法使用其清单的大部分隐式广播(即,并非专门针对此应用的广播)

针对于此我们在本篇均使用动态注册广播,稍微科普一下,广播的两种注册方式 ~

Here:不论使用哪种注册方式均需在AndroidMainest清单文件里面进行注册

  • 静态注册
    也就是说在AndroidManifest文件中对BroadcastReceiver进行注册,通常还会加上action用来过滤;此注册方式即使退出应用后,仍然能够收到相应的广播

  • 动态注册
    调用Context中的registerReceiver对广播进行动态注册,使用unRegisterReceiver方法对广播进行取消注册的操作;故此注册方式一般都是随着所在的Activity或者应用销毁以后,不会再收到该广播

动态广播提示:广播注册是一个创建的过程,那么必然也要有一个销毁的过程,从而防止内存泄露,那么销毁就在是onDestroy中unregisterReceiver广播 ~

Activity/Fragment - 注销广播

java

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //netWorkReceiver 之前已注册的广播
        if (netWorkReceiver != null) {
            unregisterReceiver(netWorkReceiver);
        }

具体实现

此处就是本文的核心内容了,网络的实时动态监听指的是全局实时监听网络状态,针对的对象非一个事件而是整个APP应用项目 ~

AndroidMainfests - 添加权限

java

 <!-- 网络状态 -->
 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

创建 - 广播接受者

  • 基础版

这里主要实时判断网络连接状态,同时判断网络类型 ~

为何说是基础版,因为这里虽然实现了功能,但是会重复收到网络变动的广播,太影响业务逻辑了!很有可能导致其他并发情况!

监听效果
在这里插入图片描述
监听实现 - NetworkReceiver(广播接收者)

java

package nk.com.networklinstener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

/**
 * @author MrLiu
 * @date 2020/5/11
 * desc 广播接收者
 */
public class NetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 监听网络连接,包括wifi和移动数据的打开和关闭,以及连接上可用的连接都会接到监听
        // 特殊注意:如果if条件生效,那么证明当前是有连接wifi或移动网络的,如果有业务逻辑最好把esle场景酌情考虑进去!
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            //获取联网状态的NetworkInfo对象
            NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
            if (info != null) {
                //如果当前的网络连接成功并且网络连接可用
                if (NetworkInfo.State.CONNECTED == info.getState() && info.isAvailable()) {
                    if (info.getType() == ConnectivityManager.TYPE_WIFI || info.getType() == ConnectivityManager.TYPE_MOBILE) {
                        Log.e("TAG", getConnectionType(info.getType()) + "已连接");
                    }
                } else {
                    Log.e("TAG", getConnectionType(info.getType()) + "已断开");
                }
            }
        }
    }

    /**
     * 获取连接类型
     * @param type
     * @return
     */
    private String getConnectionType(int type) {
        String connType = "";
        if (type == ConnectivityManager.TYPE_MOBILE) {
            connType = "3-4G网络数据";
        } else if (type == ConnectivityManager.TYPE_WIFI) {
            connType = "WIFI网络";
        }
        return connType;
    }
}
  • 优化版(推荐)

这里在判断网络连接状态的同时主要防止收到多条网络连接回调,从而导致逻辑错乱,所以采用时间校验实现类似同步锁的效果

监听效果
在这里插入图片描述
监听实现 - NetworkReceiver(广播接收者)

java

package com.nk.machine.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

import com.nk.machine.base.MainActivity;

import java.text.SimpleDateFormat;

/**
 * @author MrLiu
 * @date 2020/5/15
 * desc 广播接收者
 */
public class NetWorkReceiver extends BroadcastReceiver {
    private static long WIFI_TIME = 0;
    private static long ETHERNET_TIME = 0;
    private static long NONE_TIME = 0;
    private static int LAST_TYPE = -3;
    private static String TAG = "TAG";

    @Override
    public void onReceive(Context context, Intent intent) {
        // 监听网络连接,包括wifi和移动数据的打开和关闭,以及连接上可用的连接都会接到监听
        // 特殊注意:如果if条件生效,那么证明当前是有连接wifi或移动网络的,如果有业务逻辑最好把esle场景酌情考虑进去!
        if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
            long time = getTime();
            if (time != WIFI_TIME && time != ETHERNET_TIME && time != NONE_TIME) {
                final int netWorkState = getNetWorkState(context);
                if (netWorkState == 0 && LAST_TYPE != 0) {
                    WIFI_TIME = time;
                    LAST_TYPE = netWorkState;
                    Log.e(TAG, "wifi:" + time);
                } else if (netWorkState == 1 && LAST_TYPE != 1) {
                    ETHERNET_TIME = time;
                    LAST_TYPE = netWorkState;
                    Log.e(TAG, "数据网络:" + time);
                } else if (netWorkState == -1 && LAST_TYPE != -1) {
                    NONE_TIME = time;
                    LAST_TYPE = netWorkState;
                    Log.e(TAG, "无网络:" + time);
                }
            }
        }
    }

    public long getTime() {
        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
        String date = sDateFormat.format(new java.util.Date());
        return Long.valueOf(date);
    }
    
    private static final int NETWORK_NONE = -1; //无网络连接
    private static final int NETWORK_WIFI = 0; //wifi
    private static final int NETWORK_MOBILE = 1; //数据网络
    //判断网络状态与类型
    public static int getNetWorkState(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetworkInfo != null && activeNetworkInfo.isConnected()) {
            if (activeNetworkInfo.getType() == (ConnectivityManager.TYPE_WIFI)) {
                return NETWORK_WIFI;
            } else if (activeNetworkInfo.getType() == (ConnectivityManager.TYPE_MOBILE)) {
                return NETWORK_MOBILE;
            }
        } else {
            return NETWORK_NONE;
        }
        return NETWORK_NONE;
    }
}

MainActivity - 动态注册广播

java

package nk.com.networklinstener;

import android.annotation.SuppressLint;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private NetworkReceiver netWorkReceiver;

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //注册网络状态监听广播
        netWorkReceiver = new NetworkReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(netWorkReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (netWorkReceiver != null) {
            unregisterReceiver(netWorkReceiver);
        }
    }
}

异常场景

首先AndroidManifest加入以下权限

java

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

此异常场景指的是app在运行时有崩溃异常 - SecurityException,错误如下 ~

java

java.lang.SecurityException: com.xxx.xxx was not granted  either of these permissions: android.permission.CHANGE_NETWORK_STATE, android.permission.WRITE_SETTINGS.
    at android.os.Parcel.readException(Parcel.java:1602)
    at android.os.Parcel.readException(Parcel.java:1555)
    at android.net.IConnectivityManager$Stub$Proxy.requestNetwork(IConnectivityManager.java:2064)
    at android.net.ConnectivityManager.sendRequestForNetwork(ConnectivityManager.java:2470)
    at android.net.ConnectivityManager.requestNetwork(ConnectivityManager.java:2509)
    at com.superrtc.call.NetworkMonitorAutoDetect$ConnectivityManagerDelegate.requestMobileNetwork(NetworkMonitorAutoDetect.java)
    at com.superrtc.call.NetworkMonitorAutoDetect.<init>(NetworkMonitorAutoDetect.java)
    at com.superrtc.mediamanager.XReachability.setAutoDetectConnectivityStateInternal(XReachability.java)
    at com.superrtc.mediamanager.XReachability.startMonitoring(XReachability.java)
    at com.superrtc.mediamanager.EMediaManager$7.run(EMediaManager.java)
    at android.os.Handler.handleCallback(Handler.java:743)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:150)
    at com.superrtc.util.LooperExecutor.run(LooperExecutor.java)

按理说android.permission.CHANGE_NETWORK_STATE这一个权限,是普通权限,只在Manifest中声明就可以获取。

出现这个问题很不科学啊,再仔细去看看错误日志,发现报错只发生在6.0这个版本和部分6.0.1版本中。

那问题应该是出在6.0
版本中,之后去查资料后发现,在6.0版本中这个权限默认是被拒绝,无法获取这个权限。所以,在需要个权限的时候会出现权限问题导致应用因为权限问题崩溃。这个在stackoverflow中有人讨论过了,去看看

知道问题的原因之后的解决方案就简单了,既然CHANGE_NETWORK_STATE权限获取不到,那只好想办法打开WRITE_SETTINGS这个权限了。

跳转到应用程序设置页打开WRITE_SETTINGS这个权限:

java

Intent goToSettings = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
goToSettings.setData(Uri.parse("package:" + getPackageName()));
startActivity(goToSettings);

兴趣扩展

网络广播Actiion的三种类型

WifiManager.WIFI_STATE_CHANGED_ACTION

这个监听wifi的打开与关闭,与wifi的连接无关;示例如下,主要查看一下 wifi连接 - 关闭过程

监听效果
在这里插入图片描述
示例代码

java

package nk.com.networklinstener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.util.Log;

/**
 * @author MrLiu
 * @date 2020/5/11
 * desc wifi连接/断开过程
 */
public class NetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 监听wifi的打开与关闭,与wifi的连接无关
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
            int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
            Log.e("TAG", "wifiState:" + wifiState);
            switch (wifiState) {
                case WifiManager.WIFI_STATE_ENABLING:
                    Log.e("TAG", "wifi状态:打开中");
                    break;
                case WifiManager.WIFI_STATE_ENABLED://主用:打开状态
                    Log.e("TAG", "wifi状态:已打开");
                    break;
                case WifiManager.WIFI_STATE_DISABLING:
                    Log.e("TAG", "wifi状态:关闭中");
                    break;
                case WifiManager.WIFI_STATE_DISABLED://主用:关闭状态
                    Log.e("TAG", "wifi状态:已关闭");
                    break;
                case WifiManager.WIFI_STATE_UNKNOWN:
                    Log.e("TAG", "wifi状态:无法识别");
                    break;
                default:
                    Log.e("TAG", "wifi状态:未知");
                    break;
            }
        }
    }
}

WifiManager.NETWORK_STATE_CHANGED_ACTION

这个监听wifi的连接状态即是否连上了一个有效无线路由,当上边广播的状态是WifiManager.WIFI_STATE_DISABLING(wifi
关闭中)、WIFI_STATE_DISABLED(wifi 已关闭)的时候,根本不会接到这个广播。

在上边广播接到广播是WifiManager.WIFI_STATE_ENABLED(wifi
已打开)状态的同时也会接到这个广播,当然刚打开wifi肯定还没有连接到有效的无线

示例代码

java

package nk.com.networklinstener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.util.Log;

/**
 * @author MrLiu
 * @date 2020/5/11
 * desc wifi连接/断开过程
 */
public class NetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 这个监听wifi的连接状态即是否连上了一个有效无线路由,具体如上所述
        if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) {
            Parcelable parcelableExtra = intent
                    .getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
            if (null != parcelableExtra) {
                NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
                State state = networkInfo.getState();
                // 当然,这边可以更精确的确定状态
                boolean isConnected = state == State.CONNECTED;
                Log.e(TAG1, "isConnected" + isConnected);
                if (isConnected) {
                    APP.getInstance().setWifi(true);
                } else {
                    APP.getInstance().setWifi(false);
                }
            }
        }
    }
}

ConnectivityManager.CONNECTIVITY_ACTION

这个监听网络连接的设置,包括wifi和移动数据的打开和关闭;

此监听的作用范围最大!不论wifi的打开、关闭,或是连接上可用的链接都会接到监听;当然有利必有弊,那就是因为范围太广,所以效率相比上方的俩个监听要慢一些!

如果上方的俩个监听需求可用满足我们的业务需求,那么可以优先适用上方俩种监听方式搭配使用;但个人建议如果业务需求上面俩个监听满足不了的话,还是可以采用懒人方式直接用此监听!

Of Course :这里所谓的示例代码,就是最早看到的动态监听的实现部分了!

监听常用

此处主要借鉴与此

  • 获取ConnectivityManager对象

    java

    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context
    .CONNECTIVITY_SERVICE);

  • 获取 NetworkInfo对象

    java

    //但是这个方法已经过时,官网的解释如下:This method was deprecated in API level 23. This method does not support multiple connected networks of the same type. Use getAllNetworks() and
    getNetworkInfo(int networkType)
    getNetworkInfo(android.net.Network) instead.
    getNetworkInfo(Network network)
    getActiveNetwork()
    Returns a Network object corresponding to the currently active default data network.
    getActiveNetworkInfo(),Returns details about the currently active default data network.
    //这个方法已经过时,Use getAllNetworks() and getNetworkInfo(android.net.Network) instead.
    getAllNetworkInfo()

  • 综上所述,我们如果要知道当前Mobile网络或者WiFi网络是否已经连接上,总共有两种方法

方法一:API23时已过时

java

	//猜测:APP.getInstance()应该是一个关于网络相关的单例模式,主要用于app其他地方使用
    void getNetwork(Context context){
        State wifiState = null;
        State mobileState = null;

        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context
                .CONNECTIVITY_SERVICE);
        wifiState = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
        mobileState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();

        Log.d(TAG1,"wifi状态:" + wifiState + "\n mobile状态:" + mobileState);

        // 手机网络连接成功
        if (wifiState != null && mobileState != null
                && State.CONNECTED != wifiState
                && State.CONNECTED == mobileState) {
            Log.d("tag", "手机2g/3g/4g网络连接成功");

            APP.getInstance().setMobile(true);
            APP.getInstance().setWifi(false);
            APP.getInstance().setConnected(true);
        }
        // 无线网络连接成功
        else if (wifiState != null && State.CONNECTED == wifiState) {
            Log.d("tag", "无线网络连接成功");

            APP.getInstance().setMobile(false);
            APP.getInstance().setWifi(true);
            APP.getInstance().setConnected(true);

        }
        // 手机没有任何的网络
        else if (wifiState != null && mobileState != null
                && State.CONNECTED != wifiState
                && State.CONNECTED != mobileState) {
            Log.d("tag", "手机没有任何的网络");

            APP.getInstance().setMobile(false);
            APP.getInstance().setWifi(false);
            APP.getInstance().setConnected(false);
        }
    }

方法二:此处和我在上方的网络实时监听大致相同

java

	//猜测:APP.getInstance()应该是一个关于网络相关的单例模式,主要用于app其他地方使用
    void getNetwork(Context context) {
        ConnectivityManager manager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        Log.i("tag", "CONNECTIVITY_ACTION");

        NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
        // connected to the internet
        if (activeNetwork != null) {
            if (activeNetwork.isConnected()) {
                if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                    // connected to wifi
                    APP.getInstance().setWifi(true);
                    Log.e("tag", "当前WiFi连接可用 ");
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                    // connected to the mobile provider's data plan
                    APP.getInstance().setMobile(true);
                    Log.e("tag", "当前移动网络连接可用 ");
                }
            } else {
                Log.e("tag", "当前没有网络连接,请确保你已经打开网络 ");
            }
        } // not connected to the internet
        else {
            Log.e("tag", "当前没有网络连接,请确保你已经打开网络 ");
            APP.getInstance().setWifi(false);
            APP.getInstance().setMobile(false);
            APP.getInstance().setConnected(false);
        }
    }

闲来无事正好看到了屏幕打开/关闭的的监听广播,特此记录一番

java

package nk.com.networklinstener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * @author MrLiu
 * @date 2020/5/12
 * desc 此时APP可以后台运行,广播依然有效,但是如果被杀死则无法收到广播。
 *
 */
public class ScreenReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getAction()) {
            case Intent.ACTION_SCREEN_OFF:
                Log.e("屏幕广播","屏幕被关闭");
                break;
            case Intent.ACTION_SCREEN_ON:
                Log.e("屏幕广播","屏幕被打开");
                break;
        }
    }
}

ConnectivityManager监听网络更改

ConnectivityManager API 提供一个更强大的方法,用于仅在满足指定的网络条件时请求回调。首先我们获取到系统的
ConnectivityManager 服务, 并且使用 registerNetworkCallbackNetworkRequest
对象传递给系统,最终系统会通过 ConnectivityManager.NetworkCallback 回调,将网络变更情况告知给应用。

java

//获取ConnectivityManager 
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
//定义ConnectivityManager.NetworkCallback回调方法
callback = new ConnectivityManager.NetworkCallback() {
    // 可用网络接入
    public void onCapabilitiesChanged(@NotNull Network network, @NotNull NetworkCapabilities networkCapabilities) {
        super.onCapabilitiesChanged(network, networkCapabilities);
        LogUtils.d("onCapabilitiesChanged");
        checkNetworkCapabilities(networkCapabilities);
    }

    @Override
    public void onLost(@NonNull Network network) {
        super.onLost(network);
        if (cm != null) {
            Network activeNetwork = cm.getActiveNetwork();
            if (activeNetwork == null) {
                //连接不到可用网络
                return;
            }
            NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(activeNetwork);
            checkNetworkCapabilities(networkCapabilities);
        }
    }
};
NetworkRequest.Builder builder = new NetworkRequest.Builder();
if (cm != null) {
    cm.registerNetworkCallback(builder.build(), callback);
}

//判断当前网络连接情况
private void checkNetworkCapabilities(NetworkCapabilities networkCapabilities) {
    if (networkCapabilities == null) {
        return;
    }
    // 表明网络连接成功
    if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {
            // 使用WI-FI
            LogUtils.d("WIFI network");
        } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
            // 使用蜂窝网络
            LogUtils.d("mobile network");
        } else {
            // 未知网络,包括蓝牙、VPN、LoWPAN
            LogUtils.d("unknown network");
        }
    } else {
        //网络连接失败
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设备产线运维合集丨图扑数字孪生流水线,提升产品装配自动化效率

前言 图扑软件基于 HTML5&#xff08;Canvas/WebGL/WebVR&#xff09;标准的 Web 技术&#xff0c;满足了工业物联网跨平台云端化部署实施的需求&#xff0c;以低代码的形式自由构建三维数字孪生、大屏可视化、工业组态等等。从 SDK 组件库&#xff0c;到 2D 和 3D 编辑&#…

类加载器和双亲委派模型

类加载机制的第一步就是“加载”&#xff0c;即将Class文件获取二进制字节流并加载到方法区中 这个“加载”动作是放在JVM 之外去实现的&#xff0c;能够让应用程序来决定如何获取所需要的类 类和类加载器 对于任意一个类&#xff0c;都必须由加载它的类加载器和这个类本身一…

数字藏品的价值和意义

2022年以来&#xff0c;数字藏品概念在国内火热起来。从年初的《关于防范 NFT相关金融风险的倡议》到8月份央行数字货币 DCEP的正式面世&#xff0c;从中国香港首个“NFT”艺术品在香港拍卖市场成交到国内多家互联网大厂推出数字藏品平台&#xff0c;越来越多的企业开始试水数字…

Spring Cloud Alibaba--Nacos服务注册和配置中心

文章目录 一、什么是Nacos1.1、Nacos的由来1.2、Nacos的特性1.3、Nacos的下载和启动 二、Nacos服务注册2.1、代码示例2.2、各种注册中心的比较CAP定理多个注册中心比较 三、Nacos配置中心3.1、Nacos配置管理3.2、代码示例3.3、多环境多项目管理3.3.1、命名空间3.3.2、Group分组…

递归到动态规划:空间压缩技巧-纸币问题的有限张数

这个题是我们纸币问题的第三题 题目大意&#xff1a; arr是货币数组&#xff0c;其中的值都是正数。再给定一个正数aim。 每个值都认为是一张货币&#xff0c; 认为值相同的货币没有任何不同&#xff0c; 返回组成aim的方法数 例如&#xff1a;arr {1,2,1,1,2,1,2}&#xff0…

【C】模拟实现atoi,atof函数

目录 atoi函数 atof函数 模拟实现atoi&#xff0c;atof函数 1、atoi模拟实现 2、atof模拟实现 3、测试案例代码 atoi函数 atoi函数是将字符串转换成整数 函数头文件&#xff1a;#include <stdlib.h> 函数原型&#xff1a;int atoi(const char *str); 参数&…

利用结构相似性做单细胞多模态分析

多模态单细胞测序技术从多层基因组数据中提供了丰富的细胞异质性信息。然而&#xff0c;在没有正确消除模态偏差的情况下去分析联合空间&#xff0c;往往会得到比单模态分析更差的聚类结果。如何有效利用多组学额外信息来描绘细胞状态并识别有意义的信号仍然是一个重大的挑战。…

华为 VOS 移植到 TDA4VM/VH 芯片的 TI RTOS SDK 时的 bug 修复笔记

请从官网下载 TD4VM 技术参考手册&#xff0c;地址如下&#xff1a; TDA4VM 技术参考手册地址 VOS 作为静态库移植到TDA4VM/VH 芯片的 TI RTOS SDK 中 VOS 移植到 mcusw/mcal_drv/mcal/vos&#xff0c;如下&#xff1a; vos 测试应用 在 mcusw/mcuss_demos/vos_test_app …

Shell脚本之正则表达式

目录 一、正则表达式的介绍 1&#xff09;正则表达式的组成 2&#xff09;正则表达式和通配符的区别 二、基础正则表达式 1&#xff09;转义字符的运用 将特殊含义的字符转换为普通字符的含义 将普通字符转换为特殊作用的字符 2&#xff09;基础正则表达式实际应用 查…

C++ | 结构体及大小计算

C结构体及大小计算 文章目录 C结构体及大小计算struct 和 class 区别字节对齐默认对齐方式 位域使用#pragma pack(n)结构体中有结构体Reference struct 和 class 区别 结构体&#xff08;struct&#xff09;和类&#xff08;class&#xff09;有点像&#xff0c;均是定义一个数…

Activi7工作流经典实战(附:常用流程流转代码片段)

一、Activiti7介绍 Activiti正是目前使用最为广泛的开源工作流引擎。Activiti的官网地址是 https:// www.activiti.org 历经6.x和5.x两个大的版本。 1. Activiti工作流引擎 他可以将业务系统中复杂的业务流程抽取出来&#xff0c;使用专门的建模语言BPMN2.0进行定义。业务流…

彻底搞清楚Handler,再也不怕面试官

Handler Handler可以说是Android框架里面很精髓的一部分了&#xff0c;面试必问&#xff0c;用的也最多 Handler是什么&#xff1f; 提到Handler大家一定不陌生&#xff0c;我们经常用它来切换线程&#xff0c;或者是说做一些延时任务等等。最常用的地方可能就是在网络请求中…

Flask全栈解决小问题系列(1)搭建一个bootstrap开发框架

时间不多,闲话少说,实践出真知! 1.目的:为实现FlaskBootStrap开发效果,搞个开发测试项目 2.搭建项目 1)建个test-bootstrap项目,项目目录结构如下: 2)appstart.py内容如下: import json from flask import Flask,redirect,render_templateapp Flask("__main__") …

00后太卷了上班还没3年,跳到我们公司起薪18k....

都说00后已经躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。前段时间我们部门就来了个00后&#xff0c;工作都还没三年&#xff0c;跳到我们公司起薪18K&#xff0c;都快接近我了。 后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。最近和他…

Yolov5/Yolov7改进:小目标到大目标一网打尽,轻骨干重Neck的轻量级目标检测器GiraffeDet

1.GiraffeDet介绍 论文:https://arxiv.org/abs/2202.04256 🏆🏆🏆🏆🏆🏆Yolov5/Yolov7魔术师🏆🏆🏆🏆🏆🏆 ✨✨✨魔改网络、复现前沿论文,组合优化创新 🚀🚀🚀小目标、遮挡物、难样本性能提升 🍉🍉🍉定期更新不同数据集涨点情况 本文是…

gitlab上传大文件限制问题解决

gitlab上传大文件限制问题解决 前景提要&#xff1a; 今天收到同事反馈遇到gitlab 上传大文件时候报如下错误 error: RPC failed; result22, HTTP code 413 fatal: The remote end hung up unexpectedly fatal: The remote end hung up unexpectedly从报错来看是因为文件大…

什么样的冷链保温箱,既环保又实用?

冷链物流运输已经应用在了很多行业中&#xff0c;作为冷链物流运输中的重要设备——冷链保温箱&#xff0c;起到了举足轻重的作用。如果选择不当&#xff0c;选到了劣质产品&#xff0c;尤其是化学行业或者食品行业&#xff0c;就有可能造成试剂失效或者是影响粮食食品安全问题…

2023英码科技激发团队活力,提升集体凝聚力团建拓展之旅圆满结束!

5月6日&#xff0c;时至立夏&#xff0c;风暖昼长&#xff0c;万物繁茂。 在这个生机盎然、活力四射的时节&#xff0c; 尤其适合出游&#xff0c;开展有益身心健康的活动。 这一天&#xff0c;英码科技全体家人们齐聚广州白云区钟落潭&#xff0c;开展一天好玩有趣又意义深…

SVN基本操作 使用教程

01-SVN概述 1、为什么需要SVN版本控制软件 2、解决之道 SCM&#xff1a;软件配置管理 所谓的软件配置管理实际就是对软件源代码进行控制与管理 CVS&#xff1a;元老级产品 VSS&#xff1a;入门级产品 ClearCase&#xff1a;IBM公司提供技术支持&#xff0c;中坚级产品 SVN&…

C++类与对象(三)

文章目录 一.初始化列表1.初始化列表的概念2.初始化列表的注意事项 二.explicit关键字1.单参数构造函数2.多参数构造函数 三.static成员1.static成员的概念2.static成员的特性 四.友元1.概念2.友元函数3.友元类 五.内部类1.概念2.内部类的性质 六.匿名对象七.拷贝对象时编译器的…