当前位置: 首页 > news >正文

做网站的公司都是小公司网站开发用jquery吗

做网站的公司都是小公司,网站开发用jquery吗,网站建设 cms,国内的c2c网站有哪些一、背景 本文仅用于做学习总结#xff0c;转换成自己的理解#xff0c;方便需要时快速查阅#xff0c;深入研究可以去官网了解更多#xff1a;官网链接点这里 之前对接AI语音功能时#xff0c;发现有些按钮#xff08;或文本#xff09;在我没有主动注册唤醒词场景…一、背景 本文仅用于做学习总结转换成自己的理解方便需要时快速查阅深入研究可以去官网了解更多官网链接点这里     之前对接AI语音功能时发现有些按钮或文本在我没有主动注册唤醒词场景下还是响应了点击使用profiler跟踪调用堆栈才发现是使用了无障碍服务实现的。因为开发的是系统应用也没必要主动去打开无障碍服务开关于是觉得无障碍服务有很大的可发挥空间于是借助无障碍服务实现了一个显示当前展示的Window/Activity/Dialog的悬浮窗用于演示无障碍服务的用法及其强大之处。 二、用法 2.1 新建一个继承AccessibilityService的无障碍服务类并按需重写回调方法 class AccessibilityTest : AccessibilityService() {override fun onAccessibilityEvent(event: AccessibilityEvent?) {Log.d(TAG, onAccessibilityEvent: event $event)}override fun onServiceConnected() {super.onServiceConnected()Log.d(TAG, onServiceConnected: )}override fun onUnbind(intent: Intent?): Boolean {Log.d(TAG, onUnbind: intent $intent)return super.onUnbind(intent)}override fun onInterrupt() {Log.d(TAG, onInterrupt: )} }onServiceConnected():     当无障碍服务打开后有注册的交互事件发生时如果还没有连接服务这会先执行连接并回调这个方法。     问题AccessibilityServie继承Service也就是普通的服务没有绑定前台的notification等可见的界面会不会在后台过一会儿就断开了是否会导致某些时候无法捕获到交互的事件onAccessibilityEvent(event: AccessibilityEvent?):     当有注册的交互事件比如点击、长按、焦点变化等触发时会回调这个函数 event.getEventType(): 获取事件类型点击TYPE_VIEW_CLICKED长按TYPE_VIEW_LONG_CLICKED窗口状态变化TYPE_WINDOW_STATE_CHANGED详细的可以查阅AccessibilityService类的EventType注解中有枚举出所有的事件类型。event.getPackName(): 获取交互来自的包名event.getClassName(): 如果是Activity/Dialog则是其类的全路径名如果是View的话则展示当前的View全路径名。 onUnbind(intent: Intent?):     断开服务时回调用于处理一些资源释放的逻辑。onInterrupt(): 2.2 AndroidManifest.xml文件中注册无障碍服务 这个步骤和普通的Service注册有些不同需要配置permission、intent-filter和无障碍服务的xml配置文件基本都是固定的格式只是按需改一些配置项。 serviceandroid:name.accessibility.AccessibilityTestandroid:exportedtrueandroid:labelstring/accessibility_tipandroid:permissionandroid.permission.BIND_ACCESSIBILITY_SERVICEandroid:process:BackgroundServiceintent-filteraction android:nameandroid.accessibilityservice.AccessibilityService //intent-filtermeta-dataandroid:nameandroid.accessibilityserviceandroid:resourcexml/accessibility_config / /serviceservice节点配置的label标签会在无障碍服务中展示比如上面的label内容是“accessibility_tip”那么在无障碍服务中展示就会如下所示“     在/res/xml目录下新建一个accessibility_config.xml文件内容如下 ?xml version1.0 encodingutf-8? accessibility-service xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:accessibilityEventTypestypeAllMaskandroid:accessibilityFeedbackTypefeedbackGenericandroid:canRetrieveWindowContenttrueandroid:descriptionstring/accessibilty_desc /⚠️如果这里指定了包名android:packageNames的值多个包名用英文逗号分隔。则只会收到对应包名应用的事件。 android:description属性设置的就是上面的无障碍中accessibility_tip服务最下面的文案介绍。android:accessibilityEventTypes指定接收的事件类型android:accessibilityFeedbackType指定接收的反馈类型 2.3 在AccessibilityTest的onServiceConnected方法中动态设置serviceInfo AccessibilityTest-onServiceConnected(): 通过在Service连接到无障碍服务的回调调用setServiceInfo方法可以在在运行时调整无障碍服务的配置 override fun onServiceConnected() {super.onServiceConnected()Log.d(TAG, onServiceConnected: )val accessibilityServiceInfo AccessibilityServiceInfo()accessibilityServiceInfo.eventTypes (AccessibilityEvent.TYPE_WINDOWS_CHANGEDor AccessibilityEvent.TYPE_WINDOW_STATE_CHANGEDor AccessibilityEvent.TYPE_VIEW_CLICKEDor AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGEDor AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)accessibilityServiceInfo.feedbackType AccessibilityServiceInfo.FEEDBACK_ALL_MASKaccessibilityServiceInfo.notificationTimeout 0accessibilityServiceInfo.flags AccessibilityServiceInfo.DEFAULT// 如果这里指定了包名则只会收到对应包名应用的事件accessibilityServiceInfo.packageNames arrayOf(com.yanggui.animatortest)serviceInfo accessibilityServiceInfo }完成以上的步骤然后编译运行安装到手机上然后从无障碍服务中开启就能够在AccessibilityTest的onAccessibilityEvent中收到各种交互事件了。 无障碍服务跑起来后会打印如下log // 从无障碍服务中打开accessibility_tip服务回调onServiceConnected方法 14:25:34.170 D onServiceConnected: // 打开当前应用会执行onAccessibilityEvent方法回调一系列的事件信息封装在// AccessibilityEvent中 14:26:44.792 D onAccessibilityEvent: event EventType: TYPE_VIEW_CLICKED; EventTime: 7897173; PackageName: com.google.android.apps.nexuslauncher; MovementGranularity: 0; Action: 0; ContentChangeTypes: []; WindowChangeTypes: [] [ ClassName: android.widget.TextView; Text: [AnimatorTest]; ContentDescription: AnimatorTest; ItemCount: -1; CurrentItemIndex: -1; Enabled: true; Password: false; Checked: false; FullScreen: false; Scrollable: false; BeforeText: null; FromIndex: -1; ToIndex: -1; ScrollX: 0; ScrollY: 0; MaxScrollX: 0; MaxScrollY: 0; ScrollDeltaX: -1; ScrollDeltaY: -1; AddedCount: -1; RemovedCount: -1; ParcelableData: null ]; recordCount: 0 14:26:44.847 D onAccessibilityEvent: event EventType: TYPE_WINDOW_CONTENT_CHANGED; EventTime: 7897231; PackageName: com.google.android.apps.nexuslauncher; MovementGranularity: 0; Action: 0; ContentChangeTypes: [CONTENT_CHANGE_TYPE_SUBTREE]; WindowChangeTypes: [] [ ClassName: android.widget.FrameLayout; Text: []; ContentDescription: null; ItemCount: -1; CurrentItemIndex: -1; Enabled: true; Password: false; Checked: false; FullScreen: false; Scrollable: false; BeforeText: null; FromIndex: -1; ToIndex: -1; ScrollX: 0; ScrollY: 0; MaxScrollX: 0; MaxScrollY: 0; ScrollDeltaX: -1; ScrollDeltaY: -1; AddedCount: -1; RemovedCount: -1; ParcelableData: null ]; recordCount: 0 14:26:44.891 D onAccessibilityEvent: event EventType: TYPE_WINDOW_STATE_CHANGED; EventTime: 7897277; PackageName: com.yanggui.animatortest; MovementGranularity: 0; Action: 0; ContentChangeTypes: []; WindowChangeTypes: [] [ ClassName: com.yanggui.animatortest.leanback.RowsSupportFragmentActivity; Text: [AnimatorTest]; ContentDescription: null; ItemCount: -1; CurrentItemIndex: -1; Enabled: true; Password: false; Checked: false; FullScreen: true; Scrollable: false; BeforeText: null; FromIndex: -1; ToIndex: -1; ScrollX: 0; ScrollY: 0; MaxScrollX: 0; MaxScrollY: 0; ScrollDeltaX: -1; ScrollDeltaY: -1; AddedCount: -1; RemovedCount: -1; ParcelableData: null ]; recordCount: 0 14:26:44.952 D onAccessibilityEvent: event EventType: TYPE_WINDOW_STATE_CHANGED; EventTime: 7897337; PackageName: com.yanggui.animatortest; MovementGranularity: 0; Action: 0; ContentChangeTypes: []; WindowChangeTypes: [] [ ClassName: com.yanggui.animatortest.leanback.RowsSupportFragmentActivity; Text: [AnimatorTest]; ContentDescription: null; ItemCount: -1; CurrentItemIndex: -1; Enabled: true; Password: false; Checked: false; FullScreen: true; Scrollable: false; BeforeText: null; FromIndex: -1; ToIndex: -1; ScrollX: 0; ScrollY: 0; MaxScrollX: 0; MaxScrollY: 0; ScrollDeltaX: -1; ScrollDeltaY: -1; AddedCount: -1; RemovedCount: -1; ParcelableData: null ]; recordCount: 0 // 从无障碍服务中关闭accessibility_tip服务回调onUnbind方法 14:24:38.264 D onUnbind: intent Intent { cmpcom.yanggui.animatortest/.accessibility.AccessibilityTest }2.4 附反馈类型feedbackType和事件类型eventType的枚举值 反馈类型feedbackType定义在AccessibilityServiceInfo中 IntDef(flag true, prefix { FEEDBACK_ }, value {FEEDBACK_AUDIBLE,FEEDBACK_GENERIC,FEEDBACK_HAPTIC,FEEDBACK_SPOKEN,FEEDBACK_VISUAL,FEEDBACK_BRAILLE }) Retention(RetentionPolicy.SOURCE) public interface FeedbackType {}事件类型eventType定义在AccessibilityEvent中 IntDef(flag true,prefix {TYPE_},value {TYPE_VIEW_CLICKED, // 点击事件TYPE_VIEW_LONG_CLICKED, // 长按事件TYPE_VIEW_SELECTED, // view选中TYPE_VIEW_FOCUSED, // view上焦使用遥控操作的需要关注该事件TYPE_VIEW_TEXT_CHANGED, // 表示更改 android.widget.EditText的文本的事件。TYPE_WINDOW_STATE_CHANGED,TYPE_NOTIFICATION_STATE_CHANGED,TYPE_VIEW_HOVER_ENTER,TYPE_VIEW_HOVER_EXIT,TYPE_TOUCH_EXPLORATION_GESTURE_START,TYPE_TOUCH_EXPLORATION_GESTURE_END,TYPE_WINDOW_CONTENT_CHANGED,TYPE_VIEW_SCROLLED,TYPE_VIEW_TEXT_SELECTION_CHANGED,TYPE_ANNOUNCEMENT,TYPE_VIEW_ACCESSIBILITY_FOCUSED,TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED,TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,TYPE_GESTURE_DETECTION_START,TYPE_GESTURE_DETECTION_END,TYPE_TOUCH_INTERACTION_START,TYPE_TOUCH_INTERACTION_END,TYPE_WINDOWS_CHANGED,TYPE_VIEW_CONTEXT_CLICKED,TYPE_ASSIST_READING_CONTEXT,TYPE_SPEECH_STATE_CHANGE})Retention(RetentionPolicy.SOURCE)public interface EventType {}三、实现展示当前Activity/Dialog/Window信息的悬浮窗 如上介绍的无障碍服务是能够获取到各种交互事件从onAccessibilityEvent回调中可轻松拿到交互控件的packageName和className所以基于无障碍服务能力的支持也就很容易实现悬浮展示当前Activity的功能了。 3.1 全局悬浮窗的实现 这个业务点的关键知识点是能全局悬浮且不依赖Activity类型context也就是不需要windowToken参数的window类型。 private const val TAG TopActivityEvent class TopActivityEventWindow {companion object {SuppressLint(StaticFieldLeak)private var rootView: View? nullSuppressLint(StaticFieldLeak)private var tvContent: TextView? nullSuppressLint(StaticFieldLeak)private var window: TopActivityEventWindow? nullSuppressLint(StaticFieldLeak)fun showEvent(ctx: Context, pkgName: String?, activityClassName: String?) {if (window null) {initEventWindow(ctx)}if (!pkgName.isNullOrBlank() !activityClassName.isNullOrBlank()) {tvContent?.text $pkgName\n$activityClassName} else {Log.e(TAG, showEvent: pkgName $pkgName, activityClassName $activityClassName)}}private fun initEventWindow(ctx: Context) {rootView LayoutInflater.from(ctx).inflate(R.layout.layout_top_activity_window, null, false)val windowManager ctx.getSystemService(Context.WINDOW_SERVICE) as? WindowManagerwindowManager?.apply {val lp WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT)lp.type if (Build.VERSION.SDK_INT Build.VERSION_CODES.N) {WindowManager.LayoutParams.TYPE_TOAST} else if (Build.VERSION.SDK_INT Build.VERSION_CODES.S) {// android31及以上 需要使用TYPE_APPLICATION_OVERLAY才能展示使用ALERT_WINDOW会报没有权限WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY} else {WindowManager.LayoutParams.TYPE_SYSTEM_ALERT}lp.flags WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLElp.gravity Gravity.TOP or Gravity.LEFTlp.format PixelFormat.TRANSLUCENTaddView(rootView, lp)}tvContent rootView?.findViewById(R.id.top_activity_window_text)window TopActivityEventWindow()}fun dismiss(ctx: Context) {if (window ! null) {val windowManager ctx.getSystemService(Context.WINDOW_SERVICE) as? WindowManagerwindowManager?.removeView(rootView)tvContent nullrootView nullwindow null}}} }3.1 在无障碍服务的onAccessibilityEvent中调用悬浮窗的展示逻辑 override fun onAccessibilityEvent(event: AccessibilityEvent?) {Log.d(TAG, onAccessibilityEvent: event $event)if (event?.eventType AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {TopActivityEventWindow.showEvent(this.applicationContext, ${event.packageName}, ${event.className})}}3.2 实现的实际效果 捕获pixel3a-api33模拟器的Launcher展示效果 自己的demo app的主页获取效果 Dialog的捕获效果 PopupWindow获取不到待解决 四、总结 以上是自定义Android的无障碍服务的基本用法。在清单文件中注册CustomAccessibilityService在meta-datade android.accessibilityservice为key填写配置文件xml的路径关键是intent-filter节点中要写service节点要写permission然后重写onAccessiblityEvent()方法拿到交互事件、packageName、className最后只要在系统设置-无障碍打开就能很轻松实现一个自己的无障碍服务。这块定义注册Service的套路是固定的核心是理解不同属性的作用比如配置接收哪些事件类型和反馈类型指定包名的方式等其他的步骤不用纠结直接在需要时照猫画虎就好了不必花太多时间研究基础用法了。     但是无障碍服务支持的能力还远不止于此还能实现很多丰富的功能比如触发指定控件的点击从而配合语音识别实现点击、跳转等业务逻辑需要我们进一步阅读官方文档进行学习实践总结。
http://www.sczhlp.com/news/159189/

相关文章:

  • 网站侧边栏导航代码洛阳青峰网络公司做网站
  • 网站建设招标需求网络管理系统软件有哪些
  • 网站怎么做支付接口唐山网站建设汉狮怎么样
  • 临沂企业网站建站模板wordpress 歌词 插件
  • 域名注册,网站建设,好做吗门户网站建设验收报告
  • 旅游网站建设ppt模板下载外贸假发 网站
  • 口碑好的南昌网站建设2021世界500强企业排名
  • 广州市城乡和建设局网站首页做网站的程序员进什么公司好
  • 湛江网站设计七色板网站建设
  • 银川网站设计怎么样农产品网站建设投标书
  • 客户对网站设计的要求WordPress插件免费下载
  • 互联在线app开发网站个人网站服务器推荐
  • 网站备案照做网站导航条怎么弄
  • 音乐网站开发结语运营网站费用
  • 网站模板 带后台电商平台建设实施方案
  • 南宁高端网站建设百度公司网站建设
  • 怪兽网站模板爱站查询工具
  • 手机网站设计欣赏网站公司网站建设费会计分录
  • 网站建设需要的一些技术网站手机版怎么做
  • 备案的网站名与公司名称邯郸wap网站建设公司
  • 深圳网站建设首选开江住房和城乡建设部网站
  • 长春网站建设及推广黄岛开发区网站制作
  • 在哪个网站做问卷好网站建设欲网站维护
  • 蚌埠网站制作公司排名东莞公司网站制作要多少钱
  • 企业网站app开发平台微信网页手机登录入口
  • w7系统那个网站做的好网络游戏对青少年的危害
  • 多个页面网站的制作方法制作动画片的软件
  • 泌阳县网站建设域名到期如何续费
  • 卡二卡四无卡国产网站wordpress 添加标签
  • 丁香人才网官方网站广告宣传语