Android如何通过aspectj打造一个无侵入式动态权限申请框架
目录
一,背景
二,通过Aspectj管理所有的注解
三,配置注解
四,通过空白Activity完成真正的权限申请
五,引入依赖配置
一,背景
在Activity或者fragment中,写在几个方法写一些注释,用来表示权限申请成功
,申请失败
,多次拒绝
。同时需要无侵入式,让业务开发者尽可能的少些代码,把核心的业务逻辑下沉到框架层
二,通过Aspectj管理所有的注解
它的作用就是劫持被注释的方法的执行。我在ASPECT中配置拦截@permission注释的方法。先做判断。如果没有了解过Aspect的话,AOP面向切面编程,大家应该听说过,它可以用来配置事务、做日志、权限验证、在用户请求时做一些处理等等。而用@Aspect做一个切面,就可以直接实现。
package com.example.myapplication;import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;import java.lang.reflect.Method;import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;@Aspect
public class PermissionAspect {//com.example.myapplicationprivate static final String POINTCUT_METHOD = "execution(@com.example.myapplication.Permission * *(..))";@Pointcut(POINTCUT_METHOD)public void methodAnnotatedWithPermission() {}@Around("methodAnnotatedWithPermission()")public Object permissionMethod(final ProceedingJoinPoint joinPoint) throws Throwable {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();Permission permission = method.getAnnotation(Permission.class);String[] permissions = permission.value();int requestCode = permission.requestCode();Object object = joinPoint.getThis();Context context = null;if (object instanceof Activity) {context = (Activity) object;} else if (object instanceof FragmentActivity) {context = (FragmentActivity) object;} else if (object instanceof Fragment) {context = ((Fragment) object).getContext();} else if (object instanceof Service) {context = (Service) object;}Object o = null;if (checkPermissions(context, permissions)) {o = joinPoint.proceed();} else {Intent intent = new Intent();intent.setClass(context, PermissionActivity.class);intent.putExtra("permissions", permissions);intent.putExtra("requestcode", requestCode);context.startActivity(intent);}return o;}private boolean checkPermission(Context context, String permission) {if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) {return true;}return false;}private boolean checkPermissions(Context context, String[] permissions) {for(String permission : permissions) {if (!checkPermission(context, permission)) {return false;}}return true;}}
这样@Permission就被切点劫持了,然后方法就会跑到切面aProceedingJoinPoint。然后获取上下文Context,把权限请求交给一个透明的Activity来做。做完之后判断结果,用户是同意了还是拒绝了还是曲线了。同意了直接执行point.proceed(),其他方式则通过Activity或者fragment获取带注解的方法,反射执行即可。
三,配置注解
package com.example.myapplication;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {String[] value();int requestCode() default 1;
}
四,通过空白Activity完成真正的权限申请
package com.example.myapplication;import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;import java.util.ArrayList;
import java.util.List;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;public class PermissionActivity extends Activity {private String[] permissions;private int requestCode;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);Intent intent = getIntent();permissions = intent.getStringArrayExtra("permissions");requestCode = intent.getIntExtra("requestcode", 0);setContentView(R.layout.activity_permission);if (permissions != null && permissions.length > 0) {requestPermission(permissions);}}private void requestPermission(String[] permissions) {List<String> failure = new ArrayList<>();for (String permission : permissions) {if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {failure.add(permission);}}if (failure.size() == 0) {requestPermissionSuccess();return;}ActivityCompat.requestPermissions(this, failure.toArray(new String[]{}), requestCode);}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {if (requestCode == this.requestCode) {if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {requestPermissionSuccess();} else {boolean alwaysHidePermission = false;for (int i = 0; i < grantResults.length; i++) {if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {//判断是否勾选禁止后不再询问boolean showRequestPermission = ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i]);if (!showRequestPermission) {alwaysHidePermission = true;}}}requestPermissionFailed();}}super.onRequestPermissionsResult(requestCode, permissions, grantResults);}private void requestPermissionSuccess() {setResult(RESULT_OK);finish();}private void requestPermissionFailed() {setResult(RESULT_CANCELED);finish();}
}
五,引入依赖配置
apply plugin: 'com.android.application'buildscript {repositories {mavenCentral()}dependencies {classpath 'org.aspectj:aspectjtools:1.8.9'classpath 'org.aspectj:aspectjweaver:1.8.9'}
}android {compileSdkVersion 29buildToolsVersion "29.0.2"defaultConfig {applicationId "com.netease.premissionstudy"minSdkVersion 19targetSdkVersion 29versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}
}dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])implementation 'androidx.appcompat:appcompat:1.1.0'implementation 'androidx.constraintlayout:constraintlayout:1.1.3'testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test.ext:junit:1.1.1'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'implementation 'org.aspectj:aspectjrt:1.8.13'
}import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Mainfinal def log = project.logger
final def variants = project.android.applicationVariantsvariants.all { variant ->if (!variant.buildType.isDebuggable()) {log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")return;}JavaCompile javaCompile = variant.javaCompilejavaCompile.doLast {String[] args = ["-showWeaveInfo","-1.8","-inpath", javaCompile.destinationDir.toString(),"-aspectpath", javaCompile.classpath.asPath,"-d", javaCompile.destinationDir.toString(),"-classpath", javaCompile.classpath.asPath,"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]log.debug "ajc args: " + Arrays.toString(args)MessageHandler handler = new MessageHandler(true);new Main().run(args, handler);for (IMessage message : handler.getMessages(null, true)) {switch (message.getKind()) {case IMessage.ABORT:case IMessage.ERROR:case IMessage.FAIL:log.error message.message, message.thrownbreak;case IMessage.WARNING:log.warn message.message, message.thrownbreak;case IMessage.INFO:log.info message.message, message.thrownbreak;case IMessage.DEBUG:log.debug message.message, message.thrownbreak;}}}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {repositories {google()jcenter()}dependencies {classpath 'com.android.tools.build:gradle:3.5.2'classpath 'org.aspectj:aspectjtools:1.8.9'classpath 'org.aspectj:aspectjweaver:1.8.9'// NOTE: Do not place your application dependencies here; they belong// in the individual module build.gradle files}
}allprojects {repositories {google()jcenter()}
}task clean(type: Delete) {delete rootProject.buildDir
}
相关文章:
Android如何通过aspectj打造一个无侵入式动态权限申请框架
目录 一,背景 二,通过Aspectj管理所有的注解 三,配置注解 四,通过空白Activity完成真正的权限申请 五,引入依赖配置 一,背景 在Activity或者fragment中,写在几个方法写一些注释,用来表示权限申请成功,申请失败,多次拒绝。…...
Flink介绍——实时计算核心论文之Dataflow论文详解
引入 在过去的几篇文章里,我们看到了大数据的流式处理系统是如何一步一步进化的。从最早出现的S4,到能够做到“至少一次”处理的Storm,最后是能够做到“正好一次”数据处理的MillWheel。我们会发现,这些流式处理框架,…...
浅克隆(--depth 1)后如何获取完整的历史记录
如果远程remote为origin,则origin可以不写,如不是,则必须要写 获取全部分支 git fetch origin refs/heads/*:refs/remotes/origin/* 单独获取master分支 git fetch origin refs/heads/master:refs/remotes/origin/master 获取全部历史…...
安宝特案例 | 某知名日系汽车制造厂,借助AR实现智慧化转型
案例介绍 在全球制造业加速数字化的背景下,工厂的生产管理与设备维护效率愈发重要。 某知名日系汽车制造厂当前面临着设备的实时监控、故障维护,以及跨地域的管理协作等挑战,由于场地分散和突发状况的不可预知性,传统方式已无法…...
Feign 深度解析:Java 声明式 HTTP 客户端的终极指南
Feign 深度解析:Java 声明式 HTTP 客户端的终极指南 Feign 是由 Netflix 开源的 声明式 HTTP 客户端,后成为 Spring Cloud 生态的核心组件(现由 OpenFeign 维护)。它通过注解和接口定义简化了服务间 RESTful 通信,并…...
WPS Office安卓版云文档同步速度与PDF转换体验测评
WPS Office安卓版是很多人常用的移动办公软件。它支持在线编辑、文档同步、格式转换等功能,适合手机和平板用户随时处理文档。我们用它配合谷歌浏览器打开网页文档时,也可以将内容快速保存到云端或转换成PDF格式使用。 先说云文档同步。在打开WPS Office…...
ARM汇编的LDM和STM指令
批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据.LDM 为加载多个寄存器,STM 为存储多个寄存器.允许一条指令传送 16 个寄存器的任何子集或所有寄存器.指令格式如下: LDM{cond}<模式> Rn{!},reglist{^} STM{cond}<模式> Rn{!}…...
Python-27:游戏英雄升级潜力评估
问题描述 小U在一款挂机游戏中拥有n个英雄。游戏中有一种历练升级机制,每天可以选择两个英雄进行历练,如果两位英雄的等级相同,则他们的等级都不会改变。如果英雄等级不同,那么等级较高的英雄会增加1级,而等级较低的英…...
【基于SprintBoot+Mybatis+Mysql】电脑商城项目之显示勾选的购物车数据和创建订单
🧸安清h:个人主页 🎥个人专栏:【Spring篇】【计算机网络】【Mybatis篇】 🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。 目录 🚀1.显示勾选的购物…...
AWS Lambda 架构深入探究
AWS Lambda 是现代云架构中最受欢迎的服务之一,因其能够在完全托管的无服务器环境中运行代码而广受认可。然而,尽管 Lambda 广受欢迎,许多开发者和架构师对它的底层运作机制却知之甚少,常常将其视为“编写能够在云端神奇运行的代码…...
信奥赛CSP-J复赛集训(DP专题)(19):P3399 丝绸之路
信奥赛CSP-J复赛集训(DP专题)(19):P3399 丝绸之路 题目背景 张骞于公元前 138 年曾历尽艰险出使过西域。加强了汉朝与西域各国的友好往来。从那以后,一队队骆驼商队在这漫长的商贸大道上行进,他…...
网络NAT类型测试
免费收录PCDN、GPU算力网站_算力收录站需要专业的PCDN、GPU算力网站收录服务吗?算力收录站为您提供高效、可信赖的收录服务,提升您的网站能见度。https://www.cdngpu.com/ 什么是 NAT:NAT代表网络地址转换,允许多个内网设备共享一…...
Postman下载安装与使用汉化版教程
简介: Postman 是一款常用的 API 测试工具,可以方便地进行接口测试、调试和文档编写。本文将详细介绍如何下载安装 Postman 并汉化,包括每个步骤的详细说明。 Postman 是一款常用的 API 测试工具,可以方便地进行接口测试、调试和…...
使用Python+OpenCV对视频抽帧保存为JPG图像
使用PythonOpenCV对视频抽帧保存为JPG图像 import os import cv2 import time#视频文件夹路径,可修改 videoPath D:\\video\\ #保存的图片文件夹路径,可修改 savePath D:\\images\\ videolist os.listdir(videoPath) if not os.path.exists(savePath…...
Java的反射机制(曼波超易懂图文版)
(✪▽✪)曼波~~~~!好的呀~让曼波用最可爱的姿势为你讲解Java反射机制吧! 🌟反射机制核心概念 曼波觉得反射就像编程世界的"魔法镜"(◕ᴗ◕✿) 可以让我们在运行时动态获取类的信息并操作类对象! // 举个栗子&#…...
【DeepSeek 学习推理】Llumnix: Dynamic Scheduling for Large Language Model Serving实验部分
6.1 实验设置 测试平台。我们使用阿里云上的16-GPU集群(包含4个GPU虚拟机,类型为ecs.gn7i-c32g1.32xlarge)。每台虚拟机配备4个NVIDIA A10(24 GB)GPU(通过PCI-e 4.0连接)、128个vCPU、752 GB内…...
运行neo4j.bat console 报错无法识别为脚本,PowerShell 教程:查看语言模式并通过注册表修改受限模式
无法将“D:\neo4j-community-4.4.38-windows\bin\Neo4j-Management\Get-Args.ps1”项识别为cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 前提配置好环境变量之后依然报上面的错…...
AI写代码之GO+Python写个爬虫系统
下面我们我们来利用AI,来用GOPython写个爬虫系统。 帮我写一个Python语言爬取数据写入Mysql的案例,信息如下: 1、Mysql数据库地址是:192.168.1.20 ,mysql用户名是:root, Mysql密码是࿱…...
【FAQ】如何配置PCoIP零客户端AWI能访问
应用场景 在安全性要求较高的环境中,禁用 AWI 并使用 PCoIP 管理控制台配置端点,建议隐藏 OSD 以提高安全性。 通过OSD和AWI: 阻止 PCoIP 管理工具管理 PCoIP 零客户端。禁用对 Tera2 PCoIP Zero Client 的 AWI 的管理访问。下次访问 AWI 或 OSD 时强…...
RAGFlow:构建高效检索增强生成流程的技术解析
引言 在当今信息爆炸的时代,如何从海量数据中快速准确地获取所需信息并生成高质量内容已成为人工智能领域的重要挑战。检索增强生成(Retrieval-Augmented Generation, RAG)技术应运而生,它将信息检索与大型语言模型(L…...
go语言中defer使用指南
目录 1.使用场景 2.执行顺序 3.for循环中的defer及defer中的闭包陷阱 4.defer与返回值的关系 5.总结 1.使用场景 在编程的时候,经常需要打开一些资源,比如数据库连接、文件、锁等,这些资源需要在用完之后释放掉,否则会造成内…...
成熟软件项目解决方案:360°全景影像显控软件系统
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/147425300 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、Open…...
域名解析体系中 IPv4/IPv6 地址切换的关键技术剖析
前言: 对接的一家学校业务,学校老师要求域名解析既能解析到ipv4地址又能解析到ipv6地址。听学校老师叙述(还是会考察v6开通率的),所以通过这个方法来实现的,域名解析到ipv6和ipv4都可以。 准备一台机器 机…...
PHP 爬虫如何获取 1688 商品详情(代码示例)
在电商领域,获取 1688 商品的详细信息对于市场分析、选品上架、库存管理和价格策略制定等方面至关重要。1688 作为国内领先的 B2B 电商平台,提供了丰富的商品数据。通过 PHP 爬虫技术,我们可以高效地获取 1688 商品的详细信息,包括…...
Mysql的redolog
保证事务持久性,用于崩溃恢复,崩溃恢复时,把redo上记载的页读到内存,对其修改,变为脏页,刷盘运用于WAL技术,将随机写改为顺序写 redo log有三种状态: 存在 redo log buffer 中&…...
C++ 哈希表
1. 哈希表的概念 在vector、list的顺序结构中,查找效率为 O ( N ) O(N) O(N),在set、map的树型结构中,查找效率为 O ( l o g 2 N ) O(log_2{N}) O(log2N),有没有更优的结构 —— 哈希表 如果让数据按照某种规则映射到某个值&a…...
【pytorch学习】土堆pytorch笔记1
学习参考 仓库 https://github.com/xiaotudui/pytorch-tutorialhttps://github.com/xiaotudui/pytorch-tutorial https://github.com/AccumulateMore/CV 参考博客 https://blog.csdn.net/weixin_44216612/article/details/124203730? https://www.morinha.cc/posts/cours…...
使用Python+OpenCV将多级嵌套文件夹下的视频文件抽帧
使用PythonOpenCV将多级嵌套文件夹下的视频文件抽帧 import os import cv2 import time# 存放视频文件的多层嵌套文件夹路径 videoPath D:\\videos\\ # 保存抽帧的图片的文件夹路径 savePath D:\\images\\if not os.path.exists(savePath):os.mkdir(savePath) video_num 0f…...
ASP.Net Web Api如何更改URL
1.找到appsettings.json 修改如下: 主要为urls的修改填本机私有地址即可 {"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": &q…...
毕业论文设计基本内容和要求:
毕业设计基本内容和要求: 研究内容 调查了解LAMP架构和PHP开发; 学习百度旅游调用的其他产品线服务并熟悉请求接口; 学习社区业务层规范; 设计并实现旅游主要模块; 技术指标 熟悉企业中流程运转的方式,…...
XML内容解析成实体类
XML解析成实体类 解析方法实体类测试 说明:直接上干货,不废话 解析方法 public static List<PlatJuMinBaoXian> parse(String xmlString) {List<PlatJuMinBaoXian> result new ArrayList<>();try {// 创建 DocumentBuilderDocumentB…...
推公式——耍杂技的牛
由图可知,只要存在一个逆序,把他们交换一下,最大风险值就会降低,答案更优,因此最优解是按照wisi从小到大升序排列,顺次计算每头牛的危险系数,最大值即是答案。 #include <iostream> #inc…...
Vue指令详解:从入门到精通
前言 Vue.js作为当下最流行的前端框架之一,其指令系统是Vue最核心的特性之一。指令是Vue模板中带有v-前缀的特殊属性,它们为HTML元素添加了特殊的响应式行为。本文将全面介绍Vue的各种指令及其用法。 一、Vue指令概述 Vue指令是带有v-前缀的特殊属性&…...
准确--CentOS 7 配置 Chrony 同步阿里云 NTP 时间服务器及手动同步指南
本文档介绍如何在 CentOS 7 系统上配置 chrony 服务,使其与阿里云 NTP 时间服务器保持时间同步,并说明如何在需要时手动触发一次立即同步。 前提条件: 拥有一台 CentOS 7 服务器。拥有 root 权限或可以使用 sudo 命令。服务器可以访问互联网 (使用公共…...
CLIP | 训练过程中图像特征和文本特征的在嵌入空间中的对齐(两个投影矩阵的学习)
在多模态学习(Multimodal Learning)中,投影矩阵 W i W_i Wi 和 W t W_t Wt 是通过训练过程学习得到的。它们的作用是将图像特征 I f I_f If 和文本特征 T f T_f Tf 映射到一个共享的嵌入空间(embedding space…...
Spring中配置 Bean 的两种方式:XML 配置 和 Java 配置类
在 Spring 框架中,配置 Bean 的方式主要有两种:XML 配置 和 Java 配置类。这两种方式都可以实现将对象注册到 Spring 容器中,并通过依赖注入进行管理。本文将详细介绍这两种配置方式的步骤,并提供相应的代码示例。 1. 使用 XML 配置的方式 步骤 创建 Spring 配置文件 创建…...
STM32 外部中断
引言:嵌入式系统中的中断革命 在嵌入式系统开发领域,中断机制堪称现代微控制器的"神经系统"。它通过高效的异步事件处理机制,彻底改变了传统轮询式系统资源利用率低下的局面。STM32作为业界领先的ARM Cortex-M系列微控制器&#x…...
4.22学习总结
开始写有关图的算法 图的一些基本概念,图的存储主要以 邻接矩阵,邻接表(数组链表的实现方式)的方式存储 邻接矩阵的优点: 表达方式简单,易于理解检查任意两个顶点间是否存在边的操作非常快适合稠密图&a…...
list底层原理
一.结构体的构建 这个用结构体更好,因为我们需要不断的访问节点,类中的成员函数一般都是私有的,需要还用友元函数什么的。 这个是我们来实现的类,我们实现的是双向带头循环链表,这个是实用性最高的一个链表的形式。 这…...
python+selenium+pytest自动化测试chrome driver版本下载
chrome浏览器chromedriver版本下载地址 https://googlechromelabs.github.io/chrome-for-testing/#stable...
发布一个npm包,更新包,删除包
发布一个npm包,更新包,删除包 如何将自己的项目 发布为一个 npm 包,并掌握 更新 和 删除 的操作流程。 🚀 一、发布一个 npm 包的完整流程 ✅ 1. 注册并登录 npm 账号 如果还没有账号,先注册: 官网注册&…...
代码随想录训练营38天 || 322. 零钱兑换 279. 完全平方数 139. 单词拆分
322. 零钱兑换 思路: 动规5部曲: 1.确定dp数组以及下标的含义: dp数组表示能凑出零钱的最少硬币数,下标表示要兑换的零钱 2.确定递推公式: j为背包容量,i为物品的下标 dp[ j ] min(dp[ j -coins[ i…...
(最新)华为 2026 届校招实习-硬件技术工程师-硬件通用/单板开发—机试题—(共14套)(每套四十题)
(最新)华为 2026 届校招实习-硬件技术工程师-硬件通用/单板开发—机试题—(共14套)(每套四十题) 本套题目为硬件通用题目,适合多个岗位方向,如下 **岗位——硬件技术工程师 岗位意向…...
IOT项目——DIY Weather Station With ESP32
开源项目:ESP32 气象站 作者:GiovanniAggiustatutto 原文链接: ESP32 气象站 温度设备塔风向标风速计雨量计框架电子元件和压力传感器家庭助理配置及应用 气象站测量温度、湿度、气压、风速和风向以及降雨量。所有数据均由 ESP32收集…...
表格识别版面还原分析-GO语言集成-表格文字识别接口
数据驱动的时代,高效处理和分析各类文档中的信息变得尤为重要。无论是金融服务中的报表分析,制造与物流行业的库存管理,还是医疗卫生领域的病历记录,快速准确地将纸质或电子表格中的数据转换为可编辑、保存的电子数据成为提升工作…...
文件上传漏洞3
1. 例题:文件上传限制 1)上传漏洞靶场介绍 项目名称: upload-labs开发语言: 使用PHP语言编写功能定位: 专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场关卡数量: 目前共21关,每关包含不同上传方式注意事项: 每关没有固定通关方法,不要自限…...
一洽智能硬件行业解决方案探索与实践
一、智能硬件行业发展现状剖析 在数字化浪潮推动下,智能硬件行业呈现蓬勃发展态势。软硬件一体化的深度融合,构建起智能化服务的核心架构,而移动应用作为连接用户与设备的重要桥梁,其作用愈发关键。深入研究该行业,可…...
什么是snmp协议?在优雅草星云智控AI物联网监控系统中如何添加设备进行监控【星云智控手册01】-优雅草卓伊凡
什么是snmp协议?在优雅草星云智控AI物联网监控系统中如何添加设备进行监控【星云智控手册01】-优雅草卓伊凡 优雅草星云智控物联网设备 本产品即将在5月15日在优雅草科技的承办下召开产品发布会,本产品需要报名参加可以通过活动行搜索星云智控进行报名…...
神经网络权重优化秘籍:梯度下降法全解析(五)
引言 在神经网络的训练过程中,权重更新是提升模型性能的关键环节,而梯度下降法及其优化算法则是实现这一关键环节的核心工具。理解并掌握这些方法,对于打造高效的神经网络模型至关重要。本文将深入剖析梯度下降法在神经网络权重更新中的应用…...
输入框仅支持英文、特殊符号、全角自动转半角 vue3
需求:封装一个输入框组件 1.只能输入英文。 2.输入的小写英文自动转大写。 3.输入的全角特殊符号自动转半角特殊字符 效果图 代码 <script setup> import { defineEmits, defineModel, defineProps } from "vue"; import { debounce } from "…...