Android广播机制

简介

        某个网络的IP范围是192.168.0.XXX,子网 掩码是255.255.255.0,那么这个网络的广播地址就是192.168.0.255。广播数据包会被发送到同一 网络上的所有端口,这样在该网络中的每台主机都将会收到这条广播。为了便于进行系统级别的消息通知,Android也引入了一套类似的广播消息机制。这是因为Android中的每个应用程序都可以对自己感 兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广播可能是来自 于系统的,也可能是来自于其他应用程序的。Android提供了一套完整的API,允许应用程序自 由地发送和接收广播。发送广播的方法其实之前稍微提到过,如果你记性好的话可能还会有印 象,就是借助我们第2章学过的Intent。而接收广播的方法则需要引入一个新的概念——广播接 收器(Broadcast Receiver)。广播接收器的具体用法将会在下一节中做介绍,这里我们先来了解一下广播的类型。Android中 的广播主要可以分为两种类型:标准广播有序广播

一、广播的方式

标准广播:

        标准广播 (Normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的广播 接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。 这种广播的效率会比较高,但同时也意味着它是无法被截断的。标准广播的工作流程如图所示。

有序广播:

        有序广播 (Ordered broadcasts)则是一种同步执行的广播,在广播发出之后,同一时刻只 会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广 播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以 先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接 收器就无法收到广播消息了。有序广播的工作流程如图所示。

二、动态注册监听网络变化

        Android内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到各种系统 的状态信息。比如手机开机完成后会发出一条广播,电池的电量发生变化会发出一条广播,时 间或时区发生改变也会发出一条广播,等等。如果想要接收到这些广播,就需要使用广播接收 器,下面我们就来看一下它的具体用法。广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收 器就能够收到该广播,并在内部处理相应的逻辑。注册广播的方式一般有两种,在代码中注册(动态注册) 和在AndroidManifest.xml中注册(静态注册)。

三、动态注册

1.定义NetworkChangeReceived监听网络状态变化
第一种代码逻辑:

public class NetworkChangeReceived extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            boolean isConnected = isNetworkConnected(context);
            String statusMessage = isConnected ? "连接" : "断开";
            String networkType = NetworkType(context);
            Toast.makeText(context, "网络已" + statusMessage + ",类型" + networkType, Toast.LENGTH_SHORT).show();
        }
    }
        private boolean isNetworkConnected(Context context) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
        }
        private String NetworkType(Context context) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            return activeNetwork != null ? activeNetwork.getTypeName() : "未知";
        }
}


                                        /*代码解释*/


// 定义一个BroadcastReceiver子类,用于监听网络状态变化
public class NetworkChangeReceived extends BroadcastReceiver {
    
    // 当接收到广播时调用此方法
    @Override
    public void onReceive(Context context, Intent intent) {
        // 检查Intent的动作是否为网络连接状态改变
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            
            // 调用私有方法检查网络是否连接
            boolean isConnected = isNetworkConnected(context);
            
            // 根据网络连接状态构建提示消息
            String statusMessage = isConnected ? "连接" : "断开";
            
            // 获取网络类型
            String networkType = NetworkType(context);
            
            // 使用Toast显示网络状态和类型
            Toast.makeText(context, "网络已" + statusMessage + ",类型" + networkType, Toast.LENGTH_SHORT).show();
        }
    }

    // 私有方法,用于检查网络是否处于连接状态
    private boolean isNetworkConnected(Context context) {
        // 获取系统的ConnectivityManager服务
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
        // 获取当前活动的网络信息
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        
        // 判断网络信息是否非空并且网络正在连接或已经连接
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    // 私有方法,用于获取网络类型
    private String NetworkType(Context context) {
        // 获取系统的ConnectivityManager服务
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
        // 获取当前活动的网络信息
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        
        // 如果网络信息非空,返回网络类型名;否则返回"未知"
        return activeNetwork != null ? activeNetwork.getTypeName() : "未知";
    }
}
第二种代码逻辑:

public class NetworkChangeReceived extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            Toast.makeText(context,checkNetworkConnectionAndGetType(context), Toast.LENGTH_SHORT).show();
        }
    }
    public static String checkNetworkConnectionAndGetType(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info != null && info.isConnectedOrConnecting()) {
            // 网络已连接,返回网络类型名称
            return "连接"+info.getTypeName();
        } else {
            // 未连接网络
            return "断开";
        }
    }
}



                                        /*代码解释*/




/**
 * NetworkChangeReceived 类,继承自 BroadcastReceiver,用于监听和响应网络状态变化的广播事件。
 */
public class NetworkChangeReceived extends BroadcastReceiver {

    /**
     * 当接收到广播时调用此方法。
     * 
     * @param context 上下文,提供了应用程序的环境信息。
     * @param intent Intent 对象,包含了广播的数据和动作。
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        /**
         * 检查 Intent 的动作是否是网络状态改变的广播。
         * 如果是,则获取网络状态和类型的信息,并通过 Toast 显示给用户。
         */
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            Toast.makeText(context, checkNetworkConnectionAndGetType(context), Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 检查当前设备的网络连接状态,并返回连接状态和网络类型。
     * 
     * @param context 上下文,提供了应用程序的环境信息。
     * @return 返回一个字符串,描述了当前网络的连接状态和类型。
     */
    public static String checkNetworkConnectionAndGetType(Context context) {
        // 从系统服务中获取 ConnectivityManager 实例,用于管理网络连接。
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
        // 获取当前活动的网络信息。
        NetworkInfo info = cm.getActiveNetworkInfo();

        if (info != null && info.isConnectedOrConnecting()) {
            // 如果网络已连接,返回网络类型名称,并且前面加上"连接"两个字。
            return "连接" + info.getTypeName();
        } else {
            // 如果网络未连接,返回"断开"。
            return "断开";
        }
    }
}
2.Mainactivity中应用NetworkChangeReceived

public class MainActivity extends AppCompatActivity {
    private NetworkChangeReceived networkChangeReceived;
    private static final int PERMISSION_REQUEST_CODE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        if (ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.ACCESS_NETWORK_STATE)!=PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_NETWORK_STATE}, PERMISSION_REQUEST_CODE);
        }
        else {
            registerReceiver();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE){
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            registerReceiver();
            }
            else {
                Toast.makeText(this, "没有网络权限,无法检测网络状态", Toast.LENGTH_SHORT).show();
            }
        }
    }
    private void registerReceiver(){
        networkChangeReceived = new NetworkChangeReceived();
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(networkChangeReceived,filter);
    }

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





                                        /*代码解释*/



/**
 * MainActivity 类,继承自 AppCompatActivity,是应用的主要活动入口点。
 */
public class MainActivity extends AppCompatActivity {

    // 声明一个 NetworkChangeReceived 对象,用于接收网络状态变化的广播。
    private NetworkChangeReceived networkChangeReceived;

    // 定义一个常量,用于请求权限时的请求码。
    private static final int PERMISSION_REQUEST_CODE = 1;

    /**
     * 在 Activity 创建时调用。
     * 
     * @param savedInstanceState 可能包含先前实例状态的 Bundle 对象。
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this); // 这里假设 EdgeToEdge 是一个库的方法,用于设置全屏边缘到边缘的界面。
        
        setContentView(R.layout.activity_main); // 设置 Activity 的布局资源。

        // 检查是否已有访问网络状态的权限。
        if (ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
            // 请求访问网络状态的权限。
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_NETWORK_STATE}, PERMISSION_REQUEST_CODE);
        } else {
            // 如果已经有权限,则注册网络状态变化的广播接收器。
            registerReceiver();
        }
    }

    /**
     * 当权限请求的结果返回时调用。
     * 
     * @param requestCode 请求码,用于识别哪个权限请求的回调。
     * @param permissions 请求的权限数组。
     * @param grantResults 权限请求的结果数组。
     */
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 如果权限被授予,注册网络状态变化的广播接收器。
                registerReceiver();
            } else {
                // 如果权限被拒绝,显示一个 Toast 提示用户。
                Toast.makeText(this, "没有网络权限,无法检测网络状态", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * 注册网络状态变化的广播接收器。
     */
    private void registerReceiver() {
        networkChangeReceived = new NetworkChangeReceived();
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(networkChangeReceived, filter);
    }

    /**
     * 在 Activity 销毁时调用。
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (networkChangeReceived != null) {
            // 在 Activity 销毁前,取消注册网络状态变化的广播接收器。
            unregisterReceiver(networkChangeReceived);
        }
    }
}


四、静态注册实现开机启动

        动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大的优势,但是它也存 在着一个缺点,即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写 在onCreate() 方法中的。这里我们准备让程序接收一条开机广播,当收到这条广播时就可以在onReceive() 方法里执 行相应的逻辑,从而实现开机启动的功能。可以使用Android Studio提供的快捷方式来创建一个 广播接收器,右击com.example.broadcasttest包→New→Other→Broadcast Receiver。

创建广播接收器的窗口

Exported 属性表示是否允许 这个广播接收器接收本程序以外的广播,Enabled 属性表示是否启用这个广播接收器。勾选这 两个属性,点击Finish完成创建。

自动新建一个类,并继承BroadcastReceiver

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "My Receiver", Toast.LENGTH_LONG).show();
    }
}

五、AndroidManifest.xml文件中注册

        静态的广播接收器一定要在AndroidManifest.xml文件中注册才可以使用,不过由于我们是 使用Android Studio的快捷方式创建的广播接收器,因此注册这一步已经被自动完成了。打开 AndroidManifest.xml文件瞧一瞧,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
          <intent-filter>
              <action android:name="android.intent.action.BOOT_COMPLETED"/>
          </intent-filter>
        </receiver>

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>



                                <!-- 代码解释 -->




<?xml version="1.0" encoding="utf-8"?>
<!-- 指定文档的版本和编码方式 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <!-- 声明命名空间,定义了 Android 和工具属性的前缀 -->

    <!-- 声明应用需要的权限 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- 允许应用访问网络状态 -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <!-- 允许应用接收设备启动完成的广播 -->

    <application
        android:allowBackup="true"
        <!-- 应用的数据是否允许被备份 -->
        android:dataExtractionRules="@xml/data_extraction_rules"
        <!-- 数据提取规则,定义哪些数据可以被提取 -->
        android:fullBackupContent="@xml/backup_rules"
        <!-- 完整备份内容规则,定义哪些数据应该包含在完整备份中 -->
        android:icon="@mipmap/ic_launcher"
        <!-- 应用图标资源的引用 -->
        android:label="@string/app_name"
        <!-- 应用的显示名称 -->
        android:roundIcon="@mipmap/ic_launcher_round"
        <!-- 圆形应用图标资源的引用,适用于圆形图标显示的场景 -->
        android:supportsRtl="true"
        <!-- 是否支持从右到左的语言布局方向 -->
        android:theme="@style/Theme.MyApplication"
        <!-- 应用主题的样式引用 -->
        tools:targetApi="31">
        <!-- 工具属性,指定应用的目标 API 级别 -->

        <!-- 定义一个广播接收器 -->
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            <!-- 是否启用该接收器 -->
            android:exported="true">
            <!-- 是否允许其他应用发送广播到该接收器 -->
            <intent-filter>
                <!-- 定义接收器能够接收的广播类型 -->
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <!-- 接收设备启动完成的广播 -->
            </intent-filter>
        </receiver>

        <!-- 定义一个活动 -->
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <!-- 活动的类名和是否允许外部应用启动 -->
            <intent-filter>
                <!-- 定义活动能够响应的意图类型 -->
                <action android:name="android.intent.action.MAIN" />
                <!-- 活动是应用的入口点 -->
                <category android:name="android.intent.category.LAUNCHER" />
                <!-- 活动属于 Launcher 类别,意味着它会出现在应用启动器中 -->
            </intent-filter>
        </activity>
    </application>
</manifest>

        由于Android系统启动完成后会发出一条值为android.intent.action.BOOT_COMPLETED 的广播,因此我们在 标签里添加了相应的action。另外,监听系统开机广播 也是需要声明权限的,可以看到,我们使用 标签又加入了一 条android.permission.RECEIVE_BOOT_COMPLETED 权限。目前为止,我们在广播接收器的onReceive() 方法中都只是简单地使用Toast提示了一段文 本信息,当你真正在项目中使用到它的时候,就可以在里面编写自己的逻辑。需要注意的是, 不要在onReceive() 方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中 是不允许开启线程的,当onReceive() 方法运行了较长时间而没有结束时,程序就会报错。 因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如创建一条状态栏通知,或者 启动一个服务等,

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

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

相关文章

145-四路16位125Msps AD FMC子卡模块

一、概述 该板卡可实现4路16bit 125Msps AD 功能&#xff0c;是xilinx开发板设计的标准板卡。FMC连接器是一种高速多pin的互连器件&#xff0c;广泛应用于板卡对接的设备中&#xff0c;特别是在xilinx公司的所有开发板中都使用。该AD&#xff0c;DA子卡模块就专门针对xilinx开发…

64.函数参数和指针变量

目录 一.函数参数 二.函数参数和指针变量 三.视频教程 一.函数参数 函数定义格式&#xff1a; 类型名 函数名(函数参数1,函数参数2...) {代码段 } 如&#xff1a; int sum(int x&#xff0c;int y) {return xy; } 函数参数的类型可以是普通类型&#xff0c;也可以是指针类…

windows环境下创建python虚拟环境

windows环境下创建python虚拟环境 使用virtualenv库创建虚拟环境&#xff0c;可使不同的项目处于不同的环境中 安装方法&#xff1a; pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple pip install virtualenvwrapper-win -i https://pypi.tuna.tsinghua…

【UE5.3】笔记7 控制Pawn移动

使用A、D键控制角色左右移动 打开我们的BP_Player蓝图类&#xff0c;选择事件图表&#xff0c;添加我们的控制事件 右键&#xff0c;搜索A keyboard&#xff0c;选择A,如下图&#xff0c;D也是 添加扭矩力 首先我们要把我们的player上的模拟物理选项打开&#xff0c;这样我们…

SAPUI5基础知识10 - i18与国际化

1. 背景 i18n 是 “internationalization” 的缩写&#xff0c;其中的 18 是 “internationalization” 这个单词中间的字符数。i18n 是一种让应用程序支持多种语言的方法&#xff0c;也就是我们通常所说的国际化。 在SAPUI5中&#xff0c;i18n主要通过使用资源模型&#xff…

Matplotlib 文本

可以使用 xlabel、ylabel、text向图中添加文本 mu, sigma 100, 15 x mu sigma * np.random.randn(10000)# the histogram of the data n, bins, patches plt.hist(x, 50, densityTrue, facecolorg, alpha0.75)plt.xlabel(Smarts) plt.ylabel(Probability) plt.title(Histo…

【️讲解下Laravel为什么会成为最优雅的PHP框架?】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

540. 有序数组中的单一元素(中等)

540. 有序数组中的单一元素 1. 题目描述2.详细题解3.代码实现3.1 Python3.2 Java 1. 题目描述 题目中转&#xff1a;540. 有序数组中的单一元素 2.详细题解 方法一&#xff1a;若不限定时间复杂度&#xff0c;则扫描遍历一遍即可找到仅出现一次的数&#xff0c;具体实现见Pyth…

Maven Archetype 自定义项目模板:高效开发的最佳实践

文章目录 前言一、Maven Archetype二、创建自定义 Maven Archetype三、定制 Archetype 模板四、手动创建 Archetype 模板项目五、FAQ5.1 如何删除自定义的模板5.2 是否可以在模板中使用空文件夹 六、小结推荐阅读 前言 在软件开发中&#xff0c;标准化和快速初始化项目结构能够…

什么是JSON ,ajax和json关系

一. JSON 1 JSON概述 JavaScript对象文本表示形式&#xff08;JavaScript Object Notation : js对象简写) json是js对象 json是目前 前后端数据交互的主要格式之一 * java对象表示形式User user new User();user.setUsername("后羿");user.setAge(23);user.setSex…

开发国际短剧系统的策略解析

一、明确项目目标和需求 1、功能需求&#xff1a;确定系统应具备的基本功能&#xff0c;如用户注册、登录、浏览短剧、评论、分享、个性化推荐等。 2、性能需求&#xff1a;确保系统能够承受高并发访问&#xff0c;保证视频流畅播放&#xff0c;减少卡顿和延迟。 3、跨文化传播…

中序遍历的两种实现——二叉树专题复习

递归实现&#xff1a; /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right)…

【算法】(C语言):堆排序

堆&#xff08;二叉树的应用&#xff09;&#xff1a; 完全二叉树。最大堆&#xff1a;每个节点比子树所有节点的数值都大&#xff0c;根节点是最大值。父子索引号关系&#xff08;根节点为0&#xff09;&#xff1a;&#xff08;向上&#xff09;子节点x&#xff0c;父节点(x…

命令行升级ubuntu版本过程中出现的grub问题 解决

1、问题描述 使用命令行升级ubuntu18到20版本后&#xff0c;系统提示重启&#xff0c;使用reboot命令重启后&#xff0c;不显示服务器ip&#xff0c;或是显示但无法ssh远程连接服务器了&#xff0c;使用屏幕连接服务器后发现出现grub问题。 2、问题经过 命令行输入如下升级u…

【虚拟机】虚拟机网络无法访问问题【已解决】

【虚拟机】虚拟机无法上网问题【已解决】 问题探究解决方法法1&#xff1a;查看相关“网络服务”是否处于正常启动状态法2&#xff1a;重启网络法3&#xff1a;重新安装VMWare法4&#xff1a;使用NAT模式&#xff0c;每次打开win7都没连上网的解决办法 问题探究 安装了很多个虚…

Objection 对命令的批量操作

假定现在需要对好多不同的类进行批量hook&#xff0c;逐个hook非常繁琐&#xff0c;那么可以要将这些hook的类放到一个文件里&#xff0c;并且在这些类的前面加上hook命令&#xff0c;内容如下 使用如下命令执行该文件中的命令 objection -g 测试 explore -c d:/hookData/toHoo…

如何从腾讯云迁移到AWS

随着跨境出海潮不断扩大&#xff0c;企业越来越意识到将工作负载迁移到海外节点的必要性&#xff0c;以获取更多功能、灵活性和性能。然而&#xff0c;顺利迁移业务主机并确保业务稳定访问是一项具有挑战性的任务。在此挑战中&#xff0c;借助AWS迁移工具和迁移流程的强大支持&…

docker 安装 禅道

docker pull hub.zentao.net/app/zentao:20.1.1 sudo docker network create --subnet172.172.172.0/24 zentaonet 使用 8087端口号访问 使用禅道mysql 映射到3307 sudo docker run \ --name zentao2 \ -p 8087:80 \ -p 3307:3306 \ --networkzentaonet \ --ip 172.172.172.…

WIN32核心编程 - 进程操作(一) 进程基础 - 创建进程 - 进程句柄

公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 进程基础 进程的定义与概念 进程的组成 创建进程 可执行文件 CreateProces 执行流程 GetStartupInfo 进程终止 进程句柄 创建进程 打开进程 进程提权 内核模拟 回溯对象 自身进…

有哪些好用的eHR人事系统?国内外HR软件选型指南分享

在人力资源管理信息化这个问题上&#xff0c;不同行业的企业对人力资源管理软件的需求侧重点不一样&#xff0c;并且通常企业规模决定了企业需求的强烈程度&#xff0c;以及能花在这个软件采购上的预算。 首先需要对公司需要人力资源软件的目的和基本需求加以明确。你为什么想用…