Android SystemUI组件(06)导航栏创建分析虚拟按键

该系列文章总纲链接:专题分纲目录 Android SystemUI组件


本章关键点总结 & 说明:

说明:本章节持续迭代之前章节的思维导图,主要关注左侧SystemBars分析中导航栏部分即可。

1 导航栏创建之makeStatusBarView

通过上一篇文章的分析,我们知道 addNavigationBar是在addStatusBarWindow之后执行的,addStatusBarWindow代码实现如下:

private void addStatusBarWindow() {makeStatusBarView();//创建statusbar视图mStatusBarWindowManager = new StatusBarWindowManager(mContext);mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}

addStatusBarWindow中makeStatusBarView也执行了导航栏相关逻辑,相关代码如下:

protected PhoneStatusBarView makeStatusBarView() {final Context context = mContext;//...try {//关键点1:导航栏显示与否boolean showNav = mWindowManagerService.hasNavigationBar();//是否显示导航栏if (showNav) {//关键点2:加载导航栏布局mNavigationBarView =(NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);mNavigationBarView.setDisabledFlags(mDisabled);mNavigationBarView.setBar(this);mNavigationBarView.setOnVerticalChangedListener(new NavigationBarView.OnVerticalChangedListener() {@Overridepublic void onVerticalChanged(boolean isVertical) {if (mSearchPanelView != null) {mSearchPanelView.setHorizontal(isVertical);}mNotificationPanel.setQsScrimEnabled(!isVertical);}});//设置导航栏触摸事件mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {checkUserAutohide(v, event);return false;}});}} catch (RemoteException ex) {// no window manager? good luck with that}//...startGlyphRasterizeHack();return mStatusBarView;
}

这里主要分析两个部分:navigationBar显示与否 和 导航栏Layout相关。

1.1 navigationBar显示与否

导航栏显示与否关键在于方法mWindowManagerService.hasNavigationBar的实现,这里最终是掉用到了PhoneWindowManager中的hasNavigationBar方法。代码如下所示:

public class PhoneWindowManager implements WindowManagerPolicy {//...public boolean hasNavigationBar() {return mHasNavigationBar;}//...
}

这里变量mHasNavigationBar的赋值操作为:

mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);

这里可以看到 导航栏的配置主要是在/res/res/values中名为config_showNavigationBar的标识,即为默认的配置,如下所示:

    <!-- Whether a software navigation bar should be shown. NOTE: in the future this may beautodetected from the Configuration. --><bool name="config_showNavigationBar">false</bool>

因此,这里可以根据需求修改该配置。

1.2 导航栏Layout相关

加载导航栏布局的语句为:

NavigationBarView = (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);

从布局文件(res\layout\navigation_bar.xml)中来来看,xml文件内容如下:

<com.android.systemui.statusbar.phone.NavigationBarViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:systemui="http://schemas.android.com/apk/res-auto"android:layout_height="match_parent"android:layout_width="match_parent"android:background="@drawable/system_bar_background"><!--横向导航栏--><FrameLayout android:id="@+id/rot0"android:layout_height="match_parent"android:layout_width="match_parent"><LinearLayoutandroid:layout_height="match_parent"android:layout_width="match_parent"android:orientation="horizontal"android:clipChildren="false"android:clipToPadding="false"android:id="@+id/nav_buttons"android:animateLayoutChanges="true"><!-- navigation controls --><Viewandroid:layout_width="@dimen/navigation_side_padding"android:layout_height="match_parent"android:layout_weight="0"android:visibility="invisible"/><!--back按钮--><com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"android:layout_width="@dimen/navigation_key_width"android:layout_height="match_parent"android:src="@drawable/ic_sysbar_back"systemui:keyCode="4"android:layout_weight="0"android:scaleType="center"android:contentDescription="@string/accessibility_back"/><View android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:visibility="invisible"/><!--home按钮--><com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"android:layout_width="@dimen/navigation_key_width"android:layout_height="match_parent"android:src="@drawable/ic_sysbar_home"systemui:keyCode="3"systemui:keyRepeat="false"android:layout_weight="0"android:scaleType="center"android:contentDescription="@string/accessibility_home"/><View android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:visibility="invisible"/><!--recent按钮--><com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"android:layout_width="@dimen/navigation_key_width"android:layout_height="match_parent"android:src="@drawable/ic_sysbar_recent"android:layout_weight="0"android:scaleType="center"android:contentDescription="@string/accessibility_recent"/><FrameLayoutandroid:layout_width="@dimen/navigation_side_padding"android:layout_height="match_parent"android:layout_weight="0" ><com.android.systemui.statusbar.policy.KeyButtonViewandroid:id="@+id/menu"android:layout_width="@dimen/navigation_extra_key_width"android:layout_height="match_parent"android:contentDescription="@string/accessibility_menu"android:src="@drawable/ic_sysbar_menu"android:visibility="invisible"android:scaleType="centerInside"android:layout_gravity="end"systemui:keyCode="82" /><com.android.systemui.statusbar.policy.KeyButtonViewandroid:id="@+id/ime_switcher"android:layout_width="@dimen/navigation_extra_key_width"android:layout_height="match_parent"android:contentDescription="@string/accessibility_ime_switch_button"android:scaleType="centerInside"android:src="@drawable/ic_ime_switcher_default"android:visibility="invisible"android:layout_gravity="end" /></FrameLayout></LinearLayout><!-- lights out layout to match exactly --><LinearLayoutandroid:layout_height="match_parent"android:layout_width="match_parent"android:orientation="horizontal"android:id="@+id/lights_out"android:visibility="gone"><ImageViewandroid:layout_width="@dimen/navigation_key_width"android:layout_height="match_parent"android:layout_marginStart="@dimen/navigation_side_padding"android:src="@drawable/ic_sysbar_lights_out_dot_small"android:scaleType="center"android:layout_weight="0"/><View android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"android:visibility="invisible"/><ImageViewandroid:layout_width="@dimen/navigation_key_width"android:layout_height="match_parent"android:src="@drawable/ic_sysbar_lights_out_dot_large"android:scaleType="center"android:layout_weight="0"/><View android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"android:visibility="invisible"/><ImageViewandroid:layout_width="@dimen/navigation_key_width"android:layout_marginEnd="@dimen/navigation_side_padding"android:layout_height="match_parent"android:src="@drawable/ic_sysbar_lights_out_dot_small"android:scaleType="center"android:layout_weight="0"/></LinearLayout><com.android.systemui.statusbar.policy.DeadZoneandroid:id="@+id/deadzone"android:layout_height="match_parent"android:layout_width="match_parent"systemui:minSize="@dimen/navigation_bar_deadzone_size"systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"systemui:holdTime="@integer/navigation_bar_deadzone_hold"systemui:decayTime="@integer/navigation_bar_deadzone_decay"systemui:orientation="horizontal"android:layout_gravity="top"/></FrameLayout><!--纵向显示--><FrameLayout android:id="@+id/rot90"android:layout_height="match_parent"android:layout_width="match_parent"android:visibility="gone"android:paddingTop="0dp"><LinearLayout android:layout_height="match_parent"android:layout_width="match_parent"android:orientation="vertical"android:clipChildren="false"android:clipToPadding="false"android:id="@+id/nav_buttons"android:animateLayoutChanges="true"><!-- navigation controls --><FrameLayoutandroid:layout_weight="0"android:layout_width="match_parent"android:layout_height="@dimen/navigation_side_padding" ><com.android.systemui.statusbar.policy.KeyButtonViewandroid:id="@+id/ime_switcher"android:layout_width="match_parent"android:layout_height="@dimen/navigation_extra_key_width"android:contentDescription="@string/accessibility_ime_switch_button"android:scaleType="centerInside"android:src="@drawable/ic_ime_switcher_default"android:layout_gravity="top"android:visibility="invisible" /><com.android.systemui.statusbar.policy.KeyButtonViewandroid:id="@+id/menu"android:layout_width="match_parent"android:layout_height="40dp"android:contentDescription="@string/accessibility_menu"android:src="@drawable/ic_sysbar_menu_land"android:scaleType="centerInside"android:layout_gravity="top"android:visibility="invisible"systemui:keyCode="82" /></FrameLayout><!--recent按钮--><com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"android:layout_height="@dimen/navigation_key_width"android:layout_width="match_parent"android:src="@drawable/ic_sysbar_recent_land"android:scaleType="center"android:layout_weight="0"android:contentDescription="@string/accessibility_recent"/><View android:layout_height="match_parent"android:layout_width="match_parent"android:layout_weight="1"android:visibility="invisible"/><!--home按钮--><com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"android:layout_height="@dimen/navigation_key_width"android:layout_width="match_parent"android:src="@drawable/ic_sysbar_home_land"android:scaleType="center"systemui:keyCode="3"systemui:keyRepeat="false"android:layout_weight="0"android:contentDescription="@string/accessibility_home"/><View android:layout_height="match_parent"android:layout_width="match_parent"android:layout_weight="1"android:visibility="invisible"/><!--back按钮--><com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"android:layout_height="@dimen/navigation_key_width"android:layout_width="match_parent"android:src="@drawable/ic_sysbar_back_land"android:scaleType="center"systemui:keyCode="4"android:layout_weight="0"android:contentDescription="@string/accessibility_back"/><Viewandroid:layout_height="@dimen/navigation_side_padding"android:layout_width="match_parent"android:layout_weight="0"android:visibility="invisible"/></LinearLayout><!-- lights out layout to match exactly --><LinearLayout android:layout_height="match_parent"android:layout_width="match_parent"android:orientation="vertical"android:id="@+id/lights_out"android:visibility="gone"><ImageViewandroid:layout_height="@dimen/navigation_key_width"android:layout_marginTop="@dimen/navigation_side_padding"android:layout_width="match_parent"android:src="@drawable/ic_sysbar_lights_out_dot_small"android:scaleType="center"android:layout_weight="0"/><View android:layout_height="match_parent"android:layout_width="match_parent"android:layout_weight="1"android:visibility="invisible"/><ImageViewandroid:layout_height="@dimen/navigation_key_width"android:layout_width="match_parent"android:src="@drawable/ic_sysbar_lights_out_dot_large"android:scaleType="center"android:layout_weight="0"/><View android:layout_height="match_parent"android:layout_width="match_parent"android:layout_weight="1"android:visibility="invisible"/><ImageViewandroid:layout_height="@dimen/navigation_key_width"android:layout_marginBottom="@dimen/navigation_side_padding"android:layout_width="match_parent"android:src="@drawable/ic_sysbar_lights_out_dot_small"android:scaleType="center"android:layout_weight="0"/></LinearLayout><com.android.systemui.statusbar.policy.DeadZoneandroid:id="@+id/deadzone"android:layout_height="match_parent"android:layout_width="match_parent"systemui:minSize="@dimen/navigation_bar_deadzone_size"systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"systemui:holdTime="@integer/navigation_bar_deadzone_hold"systemui:decayTime="@integer/navigation_bar_deadzone_decay"systemui:orientation="vertical"android:layout_gravity="top"/></FrameLayout></com.android.systemui.statusbar.phone.NavigationBarView>

可以看到,横向和纵向是加载两个不同的FrameLayout配置文件。由于文件过长,这里使用简图来描述,如下:

简单解读说明如下:

  • nav_buttons:4个控件,back,home,recent,menu。
  • lights_out:多数情况不可见,当处于低辨识度模式下,nav_buttons隐藏且lights_out显示,显示为三个不明显的小灰点,降低对用户视线的干扰。
  • search_light:多数情况不可见,当HOME按键被禁后serach功能还可用,此时会变成可见,用于提示用户该功能可使用。
  • deadzone:防止边界误触操作。

导航栏显示以及布局由屏幕的方向来决定,而导航栏有两种不同的显示方式,横向显示和竖向显示,同时 我从mRotatedViews变量 分析:

public class NavigationBarView extends LinearLayout {//...View[] mRotatedViews = new View[4];//...//布局加载完成后,会回调onFinishInflate方法@Overridepublic void onFinishInflate() {//屏幕方位0和180方向显示的导航栏为rot0,90和270显示的导航栏为rot90mRotatedViews[Surface.ROTATION_0] =mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90];mCurrentView = mRotatedViews[Surface.ROTATION_0];getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);updateRTLOrder();}
}

这里也可以看到,在加载完xml文件后,会根据不同的旋转角度加载不同的layout布局文件。

2 导航栏创建之addNavigationBar 入口分析

addNavigationBar 代码实现如下:

// For small-screen devices (read: phones) that lack hardware navigation buttons
private void addNavigationBar() {if (mNavigationBarView == null) return;//关键点1prepareNavigationBarView();//关键点2: getNavigationBarLayoutParams分析mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
}

2.1 prepareNavigationBarView分析

继续分析prepareNavigationBarView,代码实现如下:

private void prepareNavigationBarView() {mNavigationBarView.reorient();//设置导航栏三个图标的点击事件mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);mNavigationBarView.getRecentsButton().setLongClickable(true);mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener);mNavigationBarView.getBackButton().setLongClickable(true);mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);updateSearchPanel();
}

导航栏布局的明确显示在prepareNavigationBarView中的mNavigationBarView.reorient();来决定,我们查看reorient方法,代码实现如下:

public void reorient() {//获取屏幕旋转方向final int rot = mDisplay.getRotation();//隐藏导航栏布局for (int i=0; i<4; i++) {mRotatedViews[i].setVisibility(View.GONE);}//根据屏幕方向显示导航栏布局mCurrentView = mRotatedViews[rot];mCurrentView.setVisibility(View.VISIBLE);getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);//初始化导航栏的转换效果,这些效果可能包括动画和过渡。mBarTransitions.init(mVertical);//根据 mDisabledFlags 设置导航栏的禁用状态setDisabledFlags(mDisabledFlags, true /* force */);//设置菜单按钮的可见性setMenuVisibility(mShowMenu, true /* force */);//如果导航栏处于横屏/垂直模式,mDelegateHelper 对象交换 X 和 Y 坐标,以适应横屏布局。if (mDelegateHelper != null) {mDelegateHelper.setSwapXY(mVertical);}updateTaskSwitchHelper();setNavigationIconHints(mNavigationIconHints, true);
}

2.2 getNavigationBarLayoutParams分析

我们回到PhoneStatusBar的addNavigationBar继续分析最后一个导航栏的LayoutParameters,它决定了导航栏在窗体上的显示位置,getNavigationBarLayoutParams代码实现如下:

private WindowManager.LayoutParams getNavigationBarLayoutParams() {/*初始化参数说明如下:FLAG_TOUCHABLE_WHEN_WAKING:当手机处于睡眠状态时,如果屏幕被按下,那么该window将第一个收到事件FLAG_NOT_FOCUSABLE:不获取焦点FLAG_NOT_TOUCH_MODAL:即使该window在可获得焦点情况下,仍然把该window之外的任何event发送到该window之后的其他windowFLAG_WATCH_OUTSIDE_TOUCH:不接受事件,转发到其他windowFLAG_SPLIT_TOUCH:当window设置这个flag,window会接收来自window边界之外发送给其他window的点击事件,支持多点触控.当这个flag没有设置的时候,第一下点击则决定了哪个window会接收整个点击事件,直到手指拿开.当设置了这个flag,这每一个点击事件(不一定是第一个)都决定了那个window来接收剩下的点击事件,直到手指拿开.点击事件会被分开传递给多个window.*/WindowManager.LayoutParams lp = new WindowManager.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,0| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,PixelFormat.TRANSLUCENT);// this will allow the navbar to run in an overlay on devices that support thisif (ActivityManager.isHighEndGfx()) {//硬件加速参数lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;}lp.setTitle("NavigationBar");//窗口名称lp.windowAnimations = 0;//不设置窗口动画return lp;
}

上面的LayoutParames决定了导航栏在窗体的大小和显示的位置效果,当然这也是受父窗口影响的,当我们有变更导航栏的显示需求时就可以同各国修正LayoutParames参数来解决。

3 导航栏虚拟按键工作原理

虚拟按键是用来替代物理按键的,而这也是导航栏最重要的工作,输入子系统(IMS)中有一个关键的方法:injectInputEvent,即直接模拟物理按键上报输入事件,它是虚拟按键的实现基础。导航栏中的KeyButtonView就是该接口使用者之一,KeyButtonView中最重要的字段是mCode,用于指示其生成的按键事件的键值。

导航栏中有4个KeyButtonView,其中back、home、menu分别产生 KEY_BACK、KEY_HOME 、KEY_MENU 三种按键事件,recent不产生按键事件。

接下来关注KeyButtonView的两个部分:从触屏事件转换到按键事件、键盘事件发送。

3.1 从触屏事件转换到按键事件

这里从KeyButtonView的onTouchEvent()方法(该方法是触屏的回调方法)开始分析,代码实现如下:

public boolean onTouchEvent(MotionEvent ev) {final int action = ev.getAction();int x, y;switch (action) {//触屏事件-按下case MotionEvent.ACTION_DOWN://Log.d("KeyButtonView", "press");mDownTime = SystemClock.uptimeMillis();setPressed(true);//如果mCode被设置有值,则发送按键事件KeyEvent.ACTION_DOWNif (mCode != 0) {sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);} else {// Provide the same haptic feedback that the system offers for virtual keys.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);}if (mSupportsLongpress) {removeCallbacks(mCheckLongPress);postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());}break;//触屏事件-移动case MotionEvent.ACTION_MOVE:x = (int)ev.getX();y = (int)ev.getY();setPressed(x >= -mTouchSlop&& x < getWidth() + mTouchSlop&& y >= -mTouchSlop&& y < getHeight() + mTouchSlop);break;//触屏事件-取消case MotionEvent.ACTION_CANCEL:setPressed(false);//如果mCode被设置有值,则发送按键事件KeyEvent.ACTION_UP,带标记KeyEvent.FLAG_CANCELEDif (mCode != 0) {sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);}if (mSupportsLongpress) {removeCallbacks(mCheckLongPress);}break;//触屏事件-抬起case MotionEvent.ACTION_UP:final boolean doIt = isPressed();setPressed(false);//如果mCode被设置有值,则发送按键事件KeyEvent.ACTION_UPif (mCode != 0) {if (doIt) {sendEvent(KeyEvent.ACTION_UP, 0);sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);playSoundEffect(SoundEffectConstants.CLICK);} else {sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);}} else {//如果没设置,则此时触发OnClickListener//导航栏会采用这种方式来处理事件// no key code, just a regular ImageViewif (doIt) {performClick();}}if (mSupportsLongpress) {removeCallbacks(mCheckLongPress);}break;}return true;
}

整个过程就是 触摸事件转换成按键事件的一个过程。

3.2 键盘事件发送

接下来专注分析KeyButtonView的sendEvent方法,代码实现如下:

public void sendEvent(int action, int flags) {sendEvent(action, flags, SystemClock.uptimeMillis());
}

继续分析,代码实现如下:

void sendEvent(int action, int flags, long when) {//计算重复次数repeatCountfinal int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;//根据参数构建KeyEvent事件final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,InputDevice.SOURCE_KEYBOARD);//将KeyEvent事件加入到InputDispatcher的派发队列。//说明:INJECT_INPUT_EVENT_MODE_ASYNC表示加入派发队列后立刻返回,不阻塞,也不等待事件派发的成功与否。InputManager.getInstance().injectInputEvent(ev,InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}

接下来最关键的就是执行InputManager的injectInputEvent方法了。这一部分属于输入子系统了,感兴趣的伙伴可查看这篇文章的后半部分:

Android Framework 输入子系统 (10)Input命令解读_input swipe

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

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

相关文章

前端 + 接口请求实现 vue 动态路由

前端 接口请求实现 vue 动态路由 在 Vue 应用中&#xff0c;通过前端结合后端接口请求来实现动态路由是一种常见且有效的权限控制方案。这种方法允许前端根据用户的角色和权限&#xff0c;动态生成和加载路由&#xff0c;而不是在应用启动时就固定所有的路由配置。 实现原理…

el-tree父子不互相关联时,手动实现全选、反选、子级全选、清空功能

el-tree父子不互相关联时&#xff0c;手动实现全选、反选、子级全选、清空功能 1、功能实现图示 2、实现思路 当属性check-strictly为true时&#xff0c;父子节点不互相关联&#xff0c;如果需要全部选中或选择某一节点下的全部节点就必须手动选择每个节点&#xff0c;十分麻…

【mysql】逻辑运算符

逻辑运算符 逻辑运算符主要是为了判断表达式的真假,返回结果也是1,0,null OR 这里面或就是两个条件或的关系,比如我要department_id等于10和等于20的情况就可以使用或. SELECT last_name,salary,department_id FROM employees WHERE department_id10 OR department_id20 …

CTF——简单的《WEB》

文章目录 一、WEB1、easysql2、baby_web3、baby_sql4、upload_easy5、easygame拓展1.1拓展1.2 6、ht_ssti7、包容乃大 一、WEB 1、easysql 题目描述&#xff1a; sql注入漏洞 1.常用的sql注入测试语句 2.sql注入bypass 解题思路 这边提示基本给的也很完整的&#xff0c;不…

C++开发基础之理解 CUDA 编译配置:`compute_XX` 和 `sm_XX` 的作用

前言 在 CUDA 编程中&#xff0c;确保代码能够在不同的 NVIDIA GPU 上高效运行是非常重要的。为了实现这一点&#xff0c;CUDA 编译器 (nvcc) 提供了多种配置选项&#xff0c;其中 compute_XX 和 sm_XX 是两个关键的编译选项。本文将深入探讨这两个选项的作用及其配置顺序&…

大一新生以此篇开启你的算法之路

各位大一计算机萌新们&#xff0c;你们好&#xff0c;本篇博客会带领大家进行算法入门&#xff0c;给各位大一萌新答疑解惑。博客文章略长&#xff0c;可根据自己的需要观看&#xff0c;在博客中会有给大一萌新问题的解答&#xff0c;请不要错过。 入门简介&#xff1a; 算法…

可信的人类与人工智能协作:基于人类反馈和物理知识的安全自主驾驶强化学习

可信的人类与人工智能协作&#xff1a;基于人类反馈和物理知识的安全自主驾驶强化学习 Abstract 在自动驾驶领域&#xff0c;开发安全且可信赖的自动驾驶策略仍然是一项重大挑战。近年来&#xff0c;结合人类反馈的强化学习&#xff08;RLHF&#xff09;因其提升训练安全性和…

中国银河资产笔试25届考什么?如何通过考试|附真题库面试攻略

嘿&#xff0c;各位小伙伴们&#xff01;我是职小豚&#xff0c;今天就带大家一起探秘中国银河资产 25 届秋招&#xff0c;为大家揭开这场金融之旅的神秘面纱。 一、中国银河资产介绍 中国银河资产&#xff0c;那可是金融领域的璀璨巨星&#xff01;它就像一座闪耀着智慧光芒…

unity安装配置和vs2022联动教程

目录 1.选择vs2022配置 2.安装unity 2.1安装unity hub 2.2注册个人账号 2.3安装编辑器 2.4修改为简体中文 2.5添加许可证 2.6安装位置修改 3.项目的创建 3.1如何创建 3.2如何选择 3.3配置语言 3.4去哪里找语言包 4.unity编辑器窗口的介绍 4.1游戏的运行和停止 4…

11、Hive+Spark数仓环境准备

1、 Hive安装部署 1&#xff09;把hive-3.1.3.tar.gz上传到linux的/opt/software目录下 2&#xff09;解压hive-3.1.3.tar.gz到/opt/module/目录下面 [shuidihadoop102 module]$ tar -zxvf /opt/software/hive-3.1.3.tar.gz -C /opt/module/ 3&#xff09;修改hive-3.1.3-b…

《深度学习》深度学习 框架、流程解析、动态展示及推导

目录 一、深度学习 1、什么是深度学习 2、特点 3、神经网络构造 1&#xff09;单层神经元 • 推导 • 示例 2&#xff09;多层神经网络 3&#xff09;小结 4、感知器 神经网络的本质 5、多层感知器 6、动态图像示例 1&#xff09;一个神经元 相当于下列状态&…

安卓开发板_联发科MTK开发评估套件串口调试

串口调试 如果正在进行lk(little kernel ) 或内核开发&#xff0c;USB 串口适配器&#xff08; USB 转串口 TTL 适配器的简称&#xff09;对于检查系统启动日志非常有用&#xff0c;特别是在没有图形桌面显示的情况下。 1.选购适配器 常用的许多 USB 转串口的适配器&#xf…

通过nginx代理转发实现共用80和443端口

目录 项目场景&#xff1a; 问题&#xff1a;怎么实现端口共用&#xff1f; 一、域名解析到nginx服务器 二、创建vhost解析到实际的服务器 三、防火墙的配置 项目场景&#xff1a; 公司自建服务器&#xff0c;有一条专线带有公网IP&#xff0c;如何满足不同的域名解析共用…

go-map系统学习

map底层结构 Goland的map的底层结构使用hash实现&#xff0c;一个hash表里有多个hash表节点&#xff0c;即bucket&#xff0c;每个bucket保存了map中的一个或者一组键值对。 map结构定义&#xff1a; runtime/map.go:hmap type hmap struct {// Note: the format of the hma…

win10 安装多个版本的python

1&#xff0c;安装python3.9 和python3.10 2, 安装完之后分别打开两个版本的Python的安装目录&#xff08;第一层目录&#xff09;&#xff0c;把pythonw.exe分别重命名为pythonw_39.exe和pythonw_310.exe&#xff0c;把python.exe复制一份&#xff0c;并分别重命名为python_…

【C++】_stack和_queue容器适配器、_deque

当别人都在关注你飞的有多高的时候&#xff0c;只有父母在关心你飞的累不累。&#x1f493;&#x1f493;&#x1f493; 目录 ✨说在前面 &#x1f34b;知识点一&#xff1a;stack •&#x1f330;1.stack介绍 •&#x1f330;2.stack的基本操作 &#x1f34b;知识点二&…

怎么利用XML发送物流快递通知短信

现如今短信平台越来越普遍了&#xff0c;而短信通知也分很多种&#xff0c;例如服务通知、订单通知、交易短信通知、会议通知等。而短信平台在物流行业通知这一块作用也很大。在家时:我们平时快递到了&#xff0c;如果电话联系不到本人&#xff0c;就会放到代收点&#xff0c;然…

力扣之1777.每家商店的产品价格

文章目录 1. 1777.每家商店的产品价格1.1 题干1.2 建表1.3 题解1.4 结果截图 1. 1777.每家商店的产品价格 1.1 题干 表&#xff1a;Products -------------------- | Column Name | Type | -------------------- | product_id | int | | store | enum | | price | int | ---…

分布式调度方案:Elastic-Job

文章目录 一、什么是分布式调度二、Elastic-Job 介绍三、Elastic-Job 实战3.1 环境搭建3.1.1 本地部署3.1.2 服务器部署3.1.3 Zookeeper 管控台界面 3.2 入门案例3.3 SpringBoot 集成 Elastic-Job3.4 任务分片&#xff08;★&#xff09;3.5 Dataflow 类型调度任务 一、什么是分…

提升LLM能力表现的四种AI代理策略

欢迎来到AI产品经理从0到1研习之旅。 “AI Agent”系列的第二篇&#xff0c;它来了&#xff01;我说过&#xff0c;AI Agent才是我最看好的&#xff08;大模型落地应用&#xff09;未来&#xff0c;嘿嘿&#xff0c;目测有很多大佬与我有相似的看法。 本文从吴恩达&#xff0…