Vue 3.2 发布, <script setup> + TS + Volar = 真香

Vue 框架创始人尤雨溪在官博宣布了 Vue 3.2版本,并且在其个人社交账号评价到:

%title插图%num

随之有用户在下面抱怨到,学不动了!

%title插图%num

哈哈,一群可爱的程序员儿~

而针对用户提到的“如果不想暴露所有变量或方法,是不是只能放弃 setup 语法糖”时,尤雨溪提醒到:“搞清楚暴露到模板和暴露到外部的区别!”

%title插图%num

下面我们一起来看看新版本都有哪些期待已久的新特性吧!

Vue 3.2 包括许多重要的新功能和性能改进,就在新版本发布后不久,官方的CHANGELOG上,又增加了一个 Vue 3.2.1更新,只更新了一个bug修复。

%title插图%num

图源:CSDN付费下载自视觉中国

%title插图%num

SFC的两个新成员顺利转正

单文件组件(SFCs,aka .vue files)的两个新功能顺利从实验状态顺利转正成稳定状态,它们分别是:

< script setup >:新的编译语法糖,简而言之就是 script setup 相当于在编译运行时把代码放到了 setup 函数中运行,然后把导出的变量定义到上下文中,并包含在返回的对象中;

<style> v-bind:即在SFC的 <style> 标签里可以绑定一些CSS内联样式。

下面是一起使用这两个功能代码的案例组件:

<script setup>import { ref } from 'vue'const color = ref('red')</script><template>  <button @click="color = color === 'red' ? 'green' : 'red'">    Color is: {{ color }}  </button></template><style scoped>button {  color: v-bind(color);}</style>

感兴趣的同学可以在SFC Playground 中尝试一番,或者阅读官方文档:

  • https://v3.vuejs.org/api/sfc-script-setup.html
  • https://v3.vuejs.org/api/sfc-style.html#state-driven-dynamic-css

此外,Vue官方基于<script setup>还构建了新的RFC,旨在通过编译器改善ref体验,体验反馈地址:https://github.com/vuejs/rfcs/discussions/369

%title插图%num

Web 组件

Vue 3.2 引入了一个新的 defineCustomElement 方法,可以使用 Vue 组件 API 轻松创建原生自定义元素:

import { defineCustomElement } from 'vue'const MyVueElement = defineCustomElement({  // normal Vue component options here})// Register the custom element.// After registration, all `<my-vue-element>` tags// on the page will be upgraded.customElements.define('my-vue-element', MyVueElement)

该API允许开发者创建Vue驱动的UI组件库,这些库可以单独使用或者与其他框架同时使用,具体如何使用,大家可以参考官方文档:https://v3.vuejs.org/guide/web-components.html

%title插图%num

性能提升

  • 对反应系统进行重大优化,感谢@basvanmeurs的出色表现
  • 更高效的ref实现(约 260% 的读取速度/约 50% 的写入速度)
  •      约 40% 更快的依赖跟踪
  •      内存使用量减少约 17%
  • 模板编译器改进:
  • 创建普通元素 VNode 的速度提升约 200%
  • 更为积*的连续 hoisting

*后,该版本还提供了可实现部分记忆模板树功能的 v-memo 新指令,该指令不但允许 Vue 可以完全跳过新的 VNode 创建步骤,还可以跳过虚拟 DOM 差异。虽然可使用的地方不多,但在特殊情况下可压榨*大性能,例如处理大型 v-for 列表。

使用简单的单行添加,v-meno 使 Vue 成为 js-framework-benchmark 中*快的主流框架:

%title插图%num

Vue官博

%title插图%num

服务端渲染

该版本的@vue/server-renderer包提供了一个 ES 模块构建,可实现与Node.js内置模块解耦。这样一来,在非Node.js 运行时中(例如CloudFlare Workers 或者 Service Workers)就可以捆绑和使用@vue/server-renderer。

与此同时,该版本还提升了流式渲染API,给 Web Streams API 渲染提供了新方法。查看@vue/server-renderer 文档可获得更多详细信息:https://github.com/vuejs/vue-next/tree/master/packages/server-renderer#streaming-api

%title插图%num

Effect Scope API

Vue 3.2 还引入了一个新的 Effect Scope API,可用来直接控制反应性效果(计算和观察者)的处理时间。它可以更轻松地在组件上下文之外使用Vue响应式API,并且解锁组件内部的一些高级用例。

这是一个面向库作者的底层API,感兴趣的同学可以查阅官方RFC了解更详细的内部原理跟案例。

相关链接:

  • Vue 变更日志:https://github.com/vuejs/vue-next/blob/master/CHANGELOG.md
  • Vue 官博发布的版本更新:https://blog.vuejs.org/posts/vue-3.2.html

————————————————

原文链接:https://blog.csdn.net/mengyidan/article/details/119562143

 

AWS 与 Elastic 矛盾再升级!

Elastic近日对其官方Python客户端(Elasticsearch-py)做出了修改,使其无法与各个分支版本相兼容。Elastic开发者向Elasticsearch-py提交了一个PR,增加了一个验证逻辑,限制用户使用Elasticsearch客户端连接到由AWS创建维护的Elasticsearch分支OpenSearch,以及跟AWS相关的Elasticsearch产品和服务,后来又关闭了GitHub上相关的话题讨论。

%title插图%num

AWS如何解决这次“危机”

面对Elastic的“主动出击”。AWS在官方博客中表示:“因为Elastic维护的开源库提供了方便的API接口,所以许多使用Elasticsearch和OpenSearch的开发人员都依赖于Elastic维护的开源客户端。修改后的客户端将无法连接到由AWS维护的Elasticsearch分支OpenSearch,以及一些版本较低的Elasticsearch开源发行版,或是托管到AWS Elasticsearch Service 的Elasticsearch。Elastic公司现在只允许应用程序连接到Elastic的商业产品上。”

不仅仅Elasticsearch的Python客户端出现问题,Elasticsearch的.NET连接器也发生了同样的事情,导致出现诸如“客户端注意到服务器不是Elasticsearch 受支持的发行版”之类的弹窗提示。另一个变化是Elasticsearch的Java客户端也已切换到Elastic License。

随着Elastic不断限制不同编程语言Elasticsearch客户端与OpenSearch产生联系。“OpenSearch 要如何处理当前可用的各种编程语言所对应的多种 connector 和 binding?“这个话题在OpenSearch社区引起了用户的焦虑。

AWS计划将在OpenSearch项目中添加一组新的开源客户端,使应用程序可以轻松连接到任何OpenSearch或Elasticsearch集群。这些客户端将允许开发人员继续运行当前版本的OpenSearch或Elasticsearch。并且用户先前的应用程序代码只需进行较少的更改,新客户端将提供他们与之前版本相同的API接口和功能。AWS计划修改的客户端包括:elasticsearch-py;elasticsearch-java;elasticsearch-net等客户端。

AWS补充到,不建议把Elastic维护的客户端更新到*新版本,因为这可能会导致应用程序中断。任何已更新其客户端并遇到问题的人都可以使用 OpenSearch文档说明,解决这些问题。他们预计在OpenSearch GitHub 组织中为每个新客户端库开放存储库。然后,迅速将客户端发布到所有相应的包管理器和存储库。确保开发人员可以轻松访问开源的Elasticsearch、Open Distro for Elasticsearch和OpenSearch客户端库。

%title插图%num

双方纠纷的由来

Elasticsearch是Elastic于2010年首次发布的分布式免费开源搜索和分析引擎,具有快速实时搜索和可靠稳定的特点。因此Elasticsearch凭借自身的优势获得众多企业的青睐,比如Adobe、Cisco、Netflix和Uber等大型企业,亚马逊的AWS云计算服务也使用Elasticsearch用来存储、搜索和分析大数据。

早在2019年1月21日,AWS曾发布Open Distro for Elasticsearch。Open Distro for Elasticsearch项目是Elasticsearch的增强版本,基于Apache 2.0 100%开源,Open Distro for Elasticsearch包含了Elasticsearch里面的商务付费功能以及Kibana的开源代码。

2021年1月15日,Elastic的创始人Shay Banon官网发文,宣布将更改开源协议,从Elastic 7.11版本开始,Elasticsearch与Kibana代码由原先遵循的 Apache 2.0许可协议调整为SSPL与Elastic License双许可协议。面对Elastic公司更改开源协议的行为,AWS回应称,Elastic这种做法只是为了自己的利益垄断,而且更改开源协议后的SSPL协议丧失了“开源精神”。AWS这样的说法,也让Elastic的创始人Shay Banon在2021年1月20日官网发文怒怼AWS,他们更改开源协议完全是因为AWS的逼迫不得以而为之,同时指责AWS本身的种种恶行。AWS也回应Elastic公司的声明,否认自己威逼Elastic公司,表示自己一系列做法完全是为了创造一个更好的开源社区,也强调自己的做法得到了很多公司的支持。

%title插图%num

业界如何看待这次纠纷

对于这次AWS与Elastic的纠纷,有开发者吐槽亚马逊本身就有“不回报开源”这个标签,而且Redis Labs、Confluent 和 MongoDB 这些公司曾经先后修改了开源协议,并明确表示修改的原因,主要为了避免像 AWS 这样的大型云服务提供商将他们的开源软件进行改版与销售。虽然AWS这次努力为OpenSearch打造成一个”完美的”开源社区,也不易改变人们对AWS的传统印象。

依旧有人认为AWS的行为是在“抢劫”开源项目,也有开发者表示,Elasticsearch属于社区的开源贡献者,Elastic没有权利保留版权,也不应该修改许可协议,他们这样做违背了开源社区的精神。

Compose Multiplatform 正式官宣,与 Flutter 必有一战?

 

%title插图%num

7月底 Compose for Android 1.0 刚刚发布,紧接着 8月4日 JetBrains 就宣布了 Compose Multiplatform 的*新进展,目前已进入 alpha 阶段。

Compose 作为一个声明式UI框架,除了渲染部分需借助平台能力以外,其他大部分特性可以做到平台无关。尤其是 Kotlin 这样一门跨平台语言,早就为日后的 UI 跨平台奠定了基础。

Compose Multiplatform 将整合现有的三个 Compose 项目:Android、Desktop、Web,未来可以像 Kotlin Multiplatform Project 一样,在一个工程下开发跨端应用,统一的声明式范式让代码在*大程度上实现复用,真正做到write once,run anywhere 。如今进入 alpah 阶段标志着其 API 也日渐成熟,相信不久的未来正式版就会与大家见面。

我们通过官方 todoapp 的例子,提前体验一下 Compose Multiplatform 的魅力 https://github.com/JetBrains/compose-jb/tree/master/examples/todoapp

%title插图%num

image.png

%title插图%num

todoapp 工程

  • todoapp
    • compose-ui :UI层可复用代码(兼容 Android 与 Desktop)
    • main:逻辑层可复用代码(首页)
    • edit:逻辑层可复用代码(编辑)
    • root:逻辑层入口、导航管理(main 与 eidt 间页面跳转)
    • utils:工具类
    • database:数据库
    • common:平台无关代码
    • android:平台相关代码,Activity等
    • desktop:平台相关代码,application等
    • web:平台相关,index.html等
    • ios:compose-ui 尚不支持 ios,但通过KMM配合SwiftUI可以实现iOS端代码

项目基于 Model-View-Intent(aka MVI) 打造,Model层、ViewModel层 代码几乎可以 100% 复用,View层在 desktop 和 Android 也可实现大部分复用,web 有一定特殊性需要单独适配。

%title插图%num

除了 Jetpack Compose 以外,项目中使用了多个基于 KM 的三方框架,保证了上层的开发范式在多平台上的一致体验:

%title插图%num

%title插图%num

todoapp 代码

平台入口代码

对比一下 Android端 与 Desktop端 的入口代码

  1. //todoapp/android/src/main/java/example/todo/android/MainActivity.ktclass MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)
  2. val root = todoRoot(defaultComponentContext())
  3. setContent { ComposeAppTheme { Surface(color = MaterialTheme.colors.background) { TodoRootContent(root) } } } }
  4. private fun todoRoot(componentContext: ComponentContext): TodoRoot = TodoRootComponent( componentContext = componentContext, storeFactory = LoggingStoreFactory(TimeTravelStoreFactory(DefaultStoreFactory())), database = DefaultTodoSharedDatabase(TodoDatabaseDriver(context = this)) )}
  1. //todoapp/desktop/src/jvmMain/kotlin/example/todo/desktop/Main.kt
  2. fun main() { overrideSchedulers(main = Dispatchers.Main::asScheduler)
  3. val lifecycle = LifecycleRegistry() val root = todoRoot(DefaultComponentContext(lifecycle = lifecycle))
  4. application { val windowState = rememberWindowState() LifecycleController(lifecycle, windowState)
  5. Window( onCloseRequest = ::exitApplication, state = windowState, title = “Todo” ) { Surface(modifier = Modifier.fillMaxSize()) { MaterialTheme { DesktopTheme { TodoRootContent(root) } } } } }}
  6. private fun todoRoot(componentContext: ComponentContext): TodoRoot = TodoRootComponent( componentContext = componentContext, storeFactory = DefaultStoreFactory(), database = DefaultTodoSharedDatabase(TodoDatabaseDriver()) )
  • TodoRootContent:根Composable,View层入口
  • TodoRootComponent:根状态管理器,ViewModel层入口
    • DefaultStoreFactory:创建 Store,管理状态
    • DefaultTodoShareDatabase:M层,数据管理

TodoRootContent 和 TodoRootComponent 分别是 View 层和 ViewModel 层的入口,TodoRootComponent 管理着全局状态,即页面导航状态。

可以看到,Android 与 Desktop 在 View 、 VM 、M等各层都进行了大面积复用,

VM层代码

MVI 中虽然没有 ViewModel,但是有等价概念,从习惯出发我们暂且称之为 VM 层。VM层其实就是状态的管理场所,我们以首页的 mian 为例

  1. //todoapp/common/main/src/commonMain/kotlin/example/todo/common/main/integration/TodoMainComponent.kt
  2. class TodoMainComponent( componentContext: ComponentContext, storeFactory: StoreFactory, database: TodoSharedDatabase, private val output: Consumer<Output>) : TodoMain, ComponentContext by componentContext {
  3. private val store = instanceKeeper.getStore { TodoMainStoreProvider( storeFactory = storeFactory, database = TodoMainStoreDatabase(database = database) ).provide() }
  4. override val models: Value<Model> = store.asValue().map(stateToModel)
  5. override fun onItemClicked(id: Long) { output(Output.Selected(id = id)) }
  6. override fun onItemDoneChanged(id: Long, isDone: Boolean) { store.accept(Intent.SetItemDone(id = id, isDone = isDone)) }
  7. override fun onItemDeleteClicked(id: Long) { store.accept(Intent.DeleteItem(id = id)) }
  8. override fun onInputTextChanged(text: String) { store.accept(Intent.SetText(text = text)) }
  9. override fun onAddItemClicked() { store.accept(Intent.AddItem) }}

了解 MVI 的朋友对上面的代码应该非常熟悉,store 管理状态并通过 models 对UI暴露,所有数据流单向流动。Value<Model> 是 Decompose 库中的类型,可以理解为跨平台的 LiveData

View层代码

@Composablefun TodoRootContent(component: TodoRoot) {    Children(routerState = component.routerState, animation = crossfadeScale()) {        when (val child = it.instance) {            is Child.Main -> TodoMainContent(child.component)            is Child.Edit -> TodoEditContent(child.component)        }    }}

TodoRootContent内部很简单,就是根据导航切换不同的页面。

具体看一下TodoMainContent

  1. @Composablefun TodoMainContent(component: TodoMain) { val model by component.models.subscribeAsState()
  2. Column { TopAppBar(title = { Text(text = “Todo List”) })
  3. Box(Modifier.weight(1F)) { TodoList( items = model.items, onItemClicked = component::onItemClicked, onDoneChanged = component::onItemDoneChanged, onDeleteItemClicked = component::onItemDeleteClicked ) }
  4. TodoInput( text = model.text, onAddClicked = component::onAddItemClicked, onTextChanged = component::onInputTextChanged ) }}

subscribeAsState() 在 Composable 中订阅了 Models 的状态,从而驱动 UI 刷新。Column 、Box 等 Composalbe 在 Descktop 和 Android 端会分别进行平台渲染。

web端代码

*后看一下web端实现。

Compose For Web 的 Composalbe 大多基于 DOM 设计,无法像 Android 和 Desktop 的 Composable 那样复用,但是 VM 和 M 层仍然可以大量复用:

  1. //todoapp/web/src/jsMain/kotlin/example/todo/web/App.ktfun main() { val rootElement = document.getElementById(“root”) as HTMLElement
  2. val lifecycle = LifecycleRegistry()
  3. val root = TodoRootComponent( componentContext = DefaultComponentContext(lifecycle = lifecycle), storeFactory = DefaultStoreFactory(), database = DefaultTodoSharedDatabase(todoDatabaseDriver()) )
  4. lifecycle.resume()
  5. renderComposable(root = rootElement) { Style(Styles)
  6. TodoRootUi(root) }}

将 TodoRootComponent 传给 UI, 协助进行导航管理

  1. @Composablefun TodoRootUi(component: TodoRoot) { Card( attrs = { style { position(Position.Absolute) height(700.px) property(“max-width”, 640.px) top(0.px) bottom(0.px) left(0.px) right(0.px) property(“margin”, auto) } } ) { val routerState by component.routerState.subscribeAsState()
  2. Crossfade( target = routerState.activeChild.instance, attrs = { style { width(100.percent) height(100.percent) position(Position.Relative) left(0.px) top(0.px) } } ) { child -> when (child) { is TodoRoot.Child.Main -> TodoMainUi(child.component) is TodoRoot.Child.Edit -> TodoEditUi(child.component) } } }}
  3. TodoMainUi 的实现如下:
  1. @Composablefun TodoMainUi(component: TodoMain) { val model by component.models.subscribeAsState()
  2. Div( attrs = { style { width(100.percent) height(100.percent) display(DisplayStyle.Flex) flexFlow(FlexDirection.Column, FlexWrap.Nowrap) } } ) { Div( attrs = { style { width(100.percent) property(“flex”, “0 1 auto”) } } ) { NavBar(title = “Todo List”) }
  3. Ul( attrs = { style { width(100.percent) margin(0.px) property(“flex”, “1 1 auto”) property(“overflow-y”, “scroll”) } } ) { model.items.forEach { item -> Item( item = item, onClicked = component::onItemClicked, onDoneChanged = component::onItemDoneChanged, onDeleteClicked = component::onItemDeleteClicked ) } }
  4. Div( attrs = { style { width(100.percent) property(“flex”, “0 1 auto”) } } ) { TodoInput( text = model.text, onTextChanged = component::onInputTextChanged, onAddClicked = component::onAddItemClicked ) } }}

%title插图%num

*后

我曾介绍过 Compose 跨平台的技术基础,如今配合各种 KM 三方库,使得开发生态更加完整。Compose Multiplatform 全程基于 Kotlin 打造,上下游同构,相对于 Flutter 和 RN 更具优势,未来可期。

韩国成功研发变色龙软体机器人;曝新iPhone将推出摄影版“人像模式”;Android 12 Beta 4发布|*客头条…

一分钟速览新闻点!

  • 美团内测饭小圈,试水外卖社交
  • 小米内部人士:雷军回忆被数落仅出于自我鞭策 不特指人和机构
  • 文件传输有改进,微信PC版3.3.5上线
  • 抖音外卖“开门营业”

  • 任正非签发!华为心声社区再发文:到该炸掉研发金字塔的时候了

  • 黑客向Poly Network返还2.6亿美元
  • 隐身技术实现重大飞跃! 韩国成功研发变色龙软体机器人
  • 曝新iPhone将着重升级影像系统,推出摄影版“人像模式”
  • 谷歌将批准8000多员工在家办公,但薪酬*高下降25%
  • 苹果iOS15公测版Beta5发布
  • TikTok下载量超过Facebook

  • Android 12 Beta 4发布

  • Android Studio Arctic Fox (2020.3.1) 稳定版正式发布

%title插图%num

国内要闻

美团内测饭小圈,试水外卖社交

继美团推出“商家群聊”后,美团围绕外卖场景再次搭建了一个社交体系。该功能于7月份开始放量内测,名为“饭小圈”,是一款基于微信好友和通讯录好友,建立社交关系的外卖分享平台。Tech星球体验后发现,美团的“饭小圈”在玩法上和朋友圈相类似,只不过分享的内容仅限于外卖订单(美食、甜品等),可以看到朋友又推荐了什么美食。目前,该功能还处于内测阶段,只能通过微信好友分享或通讯录分享,邀请开通该功能。(Tech星球)

小米内部人士:雷军回忆被数落仅出于自我鞭策不特指人和机构

小米内部人士表示,雷军演讲里回忆小米在港上市后遭遇破发、股价低迷时被投资人数落一事,并没有指责谁,也没有特别指向谁,这是一个群像,不特指任何人和机构,雷总仅仅是拿这个事来鞭策自己。该内部人士还称,没想到有人对号入座,“毕竟当时股价低,大家都在承受压力,都可以理解的”。(财联社)

文件传输有改进,微信PC版3.3.5上线

伴随着微信8.0.10 iOS版的到来,P 版微信也更新到3.3.5正式版。这次微信更新有以下特点:可以@所有人上线了,标签表情变大了;小程序新增“发送至桌面”; 同时好友验证面板也和之前有所区别,增加了标签及权限设置选项。在
文件传输面板更换了新样式,除了进度条由横改圆以外,还增加了文件体积、状态显示(上传中/发送暂停)、预计完成时间三组比较实用的参数。对自动文件进行”下载限额“,设置-文件管理-自动下载”增加了 200MB 自动限额控制,避免了微信在长期运行后过度占用磁盘空间的尴尬。视频号直播增加了“浮窗设置”、“直播画质”两项新功能。其中“直播画质”还额外增加了一个“自动配置”选项。(太平洋电脑网)

抖音外卖“开门营业”

在7月传出抖音内测“心动外卖”之后,肯德基、喜茶两家连锁餐饮品牌,已经开始在抖音上提供外卖服务。上述两个品牌,目前均通过接入小程序的方式处理外卖订单。而抖音自己推出的“心动外卖”小程序,仍处于内测阶段,且尚未对外招商。其余多数餐饮品牌和商家,仍通过发放团购优惠券的方式,吸引顾客到店消费。

任正非签发!华为心声社区再发文:到该炸掉研发金字塔的时候了

8月8日晚间,日前,华为心声社区时隔5年再次转发华为创始人兼总裁任正非2016年签发的邮件《华为到该炸掉研发金字塔的时候了》。一名华为研发员工在这篇文章中表示,华为在软件研发领域的确存在不少问题,这些问题导致华为的IT软件产品质量比较低下、开发效率低、产品交付周期漫长,很是让人痛心。

%title插图%num

%title插图%num

国际要闻

黑客向Poly Network返还2.6亿美元

跨链去中心化金融 (DeFi) 平台Poly Network在Twitter发消息称,黑客已经归还窃取资金2.6亿美元,还有3.53亿美元没有偿还。之前黑客从Poly Network窃取价值6.13亿美元的数字币,现在已归还约三分之一。

隐身技术实现重大飞跃! 韩国研发成功变色龙软体机器人

近日,韩国首尔大学的科学家以变色龙为灵感,研发出了一款可随周围环境实时变色的软体机器人。据研发者介绍,这项技术使用了颜色传感器、由银纳米线制成的微型加热器及热致变色材料,使得机器人能灵敏探测局部背景颜色随之改变。与以往的变色机器人技术相比,这款机器人的技术成本低廉,而且能应用于多种真实场合。科学家表示,希望有朝一日这项技术还能用于汽车和时尚产业等多个领域。

%title插图%num

曝新iPhone将着重升级影像系统,推出摄影版“人像模式”

根据媒体周二援引知情人士报道,除了一系列常规升级外,今年苹果将着重升级影像系统,带来至少三项拍照和摄像方面的重大升级。报道称,新款机型的摄像功能将引入此前只有拍照功能才能使用的“人像模式”,即对人物身后的背景进行虚化。此外,新iPhone 还会引入高质量视频存储格式ProRes,给后期编辑更大的操作空间。(财联社)

谷歌将批准8000多员工在家办公,但薪酬*高下降25%

据报道,如果谷歌员工选择永久在家办公,则其薪水将*高可下降25%。另外,疫情前在同一办公室工作的员工,会发现他们的薪酬有不同的变化,通勤时间长的员工受到的打击更大。(新浪科技)

WhatsApp将允许在iOS和Android设备之间传输聊天记录

移动消息应用WhatsApp正在增加可以把你的聊天记录带在身边的功能,同时支持iOS以及Android系统,能同步的数据包括所有的语音笔记、照片和对话。这项传闻已久的功能是在今天的三星发布会上宣布的,”在未来几周”将涵盖从iOS到该公司新发布的Galaxy Z Fold 3和Z Flip 3以及其他三星手机的转移。*终,该功能将涵盖所有iOS和Android手机之间的数据传输,尽管目前还不清楚它何时可用于所有设备。(cnBeta)

苹果iOS15公测版Beta5发布

苹果今天向公众测试者发布了iOS 15和iPadOS 15的*新Beta 5测试版,版本号为19A5318f,允许非开发者在秋季正式版发布前下载和测试新的系统升级。IT之家获悉,*新的Beta 5公开测试版是在苹果发布之前的Beta 4公开测试版两周后推出的,相当于昨天发布的iOS 15/iPadOS 15开发者预览版Beta 5。iOS 15增加了FaceTime的新功能,减少分心的工具,更新了通知,并增强了隐私。FaceTime支持SharePlay,用于观看电视、听音乐或与朋友分享屏幕,而“与你共享”功能可以跟踪朋友发给你的歌曲、网站链接、图片等。

TikTok下载量超过Facebook

据公布2021年6月全球热门移动应用下载量Top 10,抖音及其海外版TikTok以超过6500万下载量蝉联全球移动应用(非游戏)下载榜冠军,在App Store和Google Play上的全球安装量已超过30亿次。另外,TikTok也成为第五个安装量超30亿次的非游戏类应用,也是首个30亿次的非Facebook应用。

%title插图%num

程序员专区

谷歌Android 12 Beta 4发布

谷歌推出了安卓Android 12 Beta 4系统更新,这是第四个Beta测试版。Android 12 Beta 4本次更新的重点是稳定性方面的优化,但是仍有一些需要注意的事项:隐私仪表盘;麦克风和相机指示器;剪贴板读取通知;拉伸过度滚动;新的应用闪屏动画;Keygen 更改。 Android 12 Beta 4这次*大更新,还对后后台应用进行限制,无法自动启动前台服务。关于 Bug 修复方面,Android 12 Beta 4 修复了部分未接来电通知无法关闭的问题,修复了通知栏不显示闹钟和静音图标的问题。

更新详情查看链接:https://android-developers.googleblog.com/2021/08/android-12-beta-4-and-platform-stability.html

Android Studio Arctic Fox (2020.3.1) 稳定版正式发布

Android Studio Arctic Fox 现已正式进入稳定版发布渠道。这个*新版本支持Jetpack Compose 1.0,用于构建原生界面的Android全新工具包。另外,此版本也强调对多设备类型的覆盖,包括Wear OS设备,并提供新版后台任务管理器等功能,帮助开发者提高工作效率。针对 Jetpack Compose 添加了额外的功能从而帮助大家构建面向下一代 Android 的应用。在布局编辑器 (Layout Editor) 中增加了无障碍功能扫描器 (Accessibility Scanner),以便用户轻松地识别布局中的无障碍问题,而新的测试矩阵 (Test Matrix) 让您可以实时跨多设备并行查看测试结果。

算法也是颜值控,Twitter AI更青睐肤白貌美图

Twitter举办了“寻找AI偏见大赛”,并提供了漏洞赏金,鼓励参赛者寻找人工智能的偏见。有参赛者发现,美颜滤镜欺骗了算法。

%title插图%num

来自洛桑联邦理工学院的一名研究人员获得了3500美元的*金,因为他发现Twitter上的一种算法更青睐那些看起来苗条、年轻、白皮肤或暖肤色的面孔。Twitter于周日宣布把*金授予博丹·库利尼奇(Bogdan Kulynych)——他是一名研究隐私、安全、人工智能和社会的研究生。

Twitter赞助了这项竞赛,目的是找出“图像显著度”算法中的问题。该算法用于裁剪Twitter时间轴上的照片。传统的漏洞赏金是企业为寻找安全漏洞而付给外部人员的,而Twitter为发现AI偏见提供赏金,这也开创了区别于目前主流漏洞赏金的另一种新方式。

人工智能可以有效地处理视频字幕、识别钓鱼邮件、实现面容解锁,彻底改变了传统算法。但是,基于现实数据训练的人工智能算法可以反映真实世界的问题,解决人工智能偏差是计算机科学的一个热门领域。Twitter的悬赏就是为了发现这些问题,以便纠正。

今年年初,Twitter承认了其人工智能系统在裁剪图片的算法中存在偏见,该算法更偏向白人而非黑人的图像。但Kulynych发现了这个算法的其他问题,他认为这些问题才是核心。

研究人员Bogdan Kulynych发现,推特的AI算法通常更喜欢年轻、皮肤白、身材苗条的、被编辑过的美图。Twitter为了确定裁剪照片的方式,曾规定了“图像显著度”,现在,在符合AI审美的照片顶部、中间和底部序列的*右边都发生了变化,“图像显著度”分别增加了35%、28%和29%。

Kulynych发现:“目标模型倾向于认为那些看起来苗条、年轻、肤色明亮或温暖、皮肤光滑、面部特征偏女性化的人更突出。这种偏见可能会导致少数群体被排斥在外,数千张图片中,刻板的审美标准将延续下去。”

Kulynych所设计的系统将一张原始人脸照片的显著度与一系列人工智能生成的美图进行了比较。他发现,面孔越年轻、越瘦,显著度就越高。该算法还对肤色偏浅、偏暖、高对比度、高饱和度的照片给出了更高的分数。

Twitter高度赞扬了这项比赛,因为在这个世界上,当我们与朋友分享照片或在社交媒体上发布照片,很多人都会先使用美颜相机和修图软件,给照片加上美颜滤镜。而这可能会扭曲我们对“美”的认知。

美颜相机和修图软件很普遍,除了滤镜之外,很多软件还推出了“智能美容”功能,可以调整人物的脸型和五官。但谷歌认为,美颜滤镜会“对心理健康产生负面影响”。因此,在Pixel相机APP中他们关闭了默认的自动润色功能,该公司也不再将其调整功能称为“美容”滤镜。

原文链接:

https://www.cnet.com/tech/mobile/twitter-ai-bias-contest-shows-beauty-filters-hoodwink-the-algorithm/

MIUI *近那个原子内存是什么原理?

MIUI *近那个原子内存是什么原理?

 

ysy950803 · 1 天前 via Android · 7721 次点击

*近雷布斯的演讲有点意思,不过我更好奇那个 12.5 增强版(其实就是超级 Bug 修复版)里提到的原子内存,我看介绍大概是可以回收各个应用进程内部的局部内存,这样可以使得可用内存更多,后台被杀的概率降低。

但是这个回收局部内存是咋做到的?比我我在微信聊天,但是支付暂时用不到,可以回收,系统如何判定的?

84 条回复    2021-08-13 14:31:22 +08:00

ysy950803
    1

ysy950803   1 天前 via Android

“比我”->“比如”
AoEiuV020
    2

AoEiuV020   1 天前

这,gc ?总不可能回收有强引用的内存,那就是杀后台了,
而且我是不信 miui 内存多了就不杀后台的,我 8G 内存时常剩 4g,照样死命杀后台,
heiher
    3

heiher   1 天前 via Android   ❤️ 2

或许就是 swap 吧 😀
Mcx
    4

Mcx   1 天前

感觉是忽悠人的
tyzrj766
    5

tyzrj766   1 天前   ❤️ 1

看酷安上面说就是把一个 APP 的服务分开去杀进程,例如一个微博有多项服务,需要内存资源的时候先杀个广告服务,不够了再杀另一个,不会干掉主程序。类似之前写轮眼吧,折腾安卓的应该都用过,以前我就是把百度输入法的服务留了一两个主要的,其他没用的全关了。
yanzhiling2001
    6

yanzhiling2001   1 天前

swap
tyzrj766
    7

tyzrj766   1 天前

@tyzrj766 #5 应该不是虚拟内存那么简单的东西,倒是*近看蓝厂还是绿厂有类似的操作,把 ROM 空余的一小部分增加一小部分虚拟内存用,反正现在动不动 128G 256G 的,拿个 2G 、4G 也无所谓。
kokutou
    8

kokutou   1 天前

swap 吧..
开发版已经实装了…叫内存扩展
hello2066
    9

hello2066   1 天前   ❤️ 2

他就是原子嘛,利用原子的运动型,多样性,轨迹性。很多原子分配给各个进程,更好的监控进程嘛,预计你要开哪个,要关哪个。机器学习嘛,顶级操作系统功能,预加载,分片性,原子之间互相联系互相通讯,系统结构更紧凑响应更快。
murmur
    10

murmur   1 天前

定向杀进程吧,反正国内常用的 app 一把手就数的过来,能解决阿里腾讯头条就可以拿出来吹了

yinusxxxx
    11

yinusxxxx   1 天前

应该还是虚拟内存,把应用从 RAM 换出到 ROM 上,再加上 POSIX 提供了可以把一部分内存 pin 住不换出的系统调用,可以更加精确控制吧

Dona1d
    12

Dona1d   1 天前

@kokutou 把整个内存比作房子,进程是住客。内存扩展是增加房间,我 12G 的感觉没什么用。原子内存应该是类似在保留*基本的住的需求的情况下。如果人少,住客就能享受完整的套房,如果人多,有的住客就会分到客厅、书房、厨房来住。
yukiww233
    13

yukiww233   1 天前   ❤️ 1

看起来搜集一些主流应用的 activity 按优先级挑着杀, 而不是整个进程杀掉
但问题是, ram 占用大头不是这个啊…
感觉还是营销概念大于实际作用
pengtdyd
    14

pengtdyd   23 小时 49 分钟前   ❤️ 39

国内企业总喜欢搞这种微创新,然后起个看起来很厉害的名字,你说他有用吧,确实有用,你说他没用吧,也确实没啥用,都是鸡肋罢了.说白了还是格局被局限了,android 系统就像围城,很多企业在里面绞尽脑汁的”创新”.如果以后出现一个颠覆性的产品出现,直接改变行业规则,就像马斯克之于汽车行业一样,那么这些企业就会像跟屁虫一样,去追随下一个颠覆者.
hhjswf
    15

hhjswf   22 小时 39 分钟前

听金凡吹,我感觉 jvm 应该请他过来指导,java 就稳坐*了?
Maboroshii
    16

Maboroshii   22 小时 37 分钟前

我倒是觉得哪个存储空间碎片整理的不错,不知道原生安卓有没有第三方应用能实现这个优化的
zcfnc
    17

zcfnc   22 小时 36 分钟前

# 14 不能再同意十四楼的说法,国内的很多东西光看名字和描述都以为我们*别人几十年技术了,然后扒了皮一言难尽
xishijt
    18

xishijt   22 小时 25 分钟前

先把明明内存还剩一半,但是拼命杀后台的机制解决再说其他的
littlewing
    19

littlewing   22 小时 23 分钟前

ppt
juded
    20

juded   22 小时 20 分钟前

这个问题要问市场营销部门
qsmd42
    21

qsmd42   22 小时 7 分钟前

@hello2066 明天来华为入职!
qsmd42
    22

qsmd42   22 小时 5 分钟前   ❤️ 2

@Maboroshii 这个碎片整理我就更不明白了 闪存不是不需要碎片整理吗
jingslunt
    23

jingslunt   22 小时 0 分钟前

@hello2066 明年应该会出量子 cpu,齐点设备,抗熵增存储 怕不怕
vmebeh
    24

vmebeh   21 小时 50 分钟前 via iPhone   ❤️ 4

要不是国内软件各种骚操作、流氓一样保后台,也不需要这类东西
andyskaura
    25

andyskaura   21 小时 48 分钟前   ❤️ 1

@xishijt 拼命杀 拼命开 一边杀 一边开 只能说 生态太差了
blessingsi
    26

blessingsi   20 小时 6 分钟前

什么时候这种东西不是放在发布会上发布,而是放到开发者大会 or 发 paper 出来,让大家看看到底是个什么东西。
mu2er
    27

mu2er   17 小时 19 分钟前 via iPhone

这东西概念吹得可真厉害,像当年小米 5 发布时吹得各种黑科技,到手发现就那个样世界烂大街的功能。
chenyx9
    28

chenyx9   16 小时 58 分钟前 via Android

@jingslunt 这么大计算力的配置,耗电也挺吓人吧。建议先出氚聚变电池。
iOCZ
    29

iOCZ   16 小时 54 分钟前

感觉粒度到你说的支付功能不现实。首先你写程序你应该知道,你没用到的功能,是不太会占用内存的,其次用完了也会释放。因此减少驻留内存才是关键吧。
tanranran
    30

tanranran   16 小时 18 分钟前

楼上各种喷的人用一下就知道了,感知还是很强的
tanranran
    31

tanranran   16 小时 16 分钟前   ❤️ 6

原理是:正常情况下的安卓内存管理机制,是以 APP 的个数为基本单位的。比如你打开了微信,哪怕只是聊天,也要承担微信里比如定位、小程序、游戏。支付等功能同时唤醒带来的内存占用。要么都去掉,要么都接着。MIUI 新的 RAM 管理机制呢,则是将管理基本单位进一步细分、精确到了“项”,你打开微信,只聊天,那就只保留聊天,其他没用的功能,都给我乖乖地冷藏着。
Maskeney
    32

Maskeney   16 小时 5 分钟前

ZRAM 拉大点?
tanranran
    33

tanranran   16 小时 4 分钟前

@iOCZ 大哥,一看你就是没写过安卓,安卓中的多进程和多服务还是很好资源的
jim9606
    34

jim9606   15 小时 41 分钟前

主要问题是,当今能够大幅提升性能的改进,是少不了端对端的配合的,现在已经没有改改硬件或者系统、无需 APP 修改就能获得 buff 的事了。

而且我是很奇怪怎么这个 MIUI 连版本号都不刷了,叫个 12.6 都好些,12.5 名声已经不好了,在 marketing 角度来看,就算新版本改好了,公众也很难摆脱以前的负面印象。

@pengtdyd 革命性变化这种东西少也要 5-10 年的周期,而且初期肯定伴随着一大堆槽点的,指望一个成熟技术的常规迭代整这个就是不现实的。另外也别说只是国内公司这么干,国外公司也一样,PPT 看着牛逼的东西,要么有严苛的限定条件,要么未来可期那种。

ajaxfunction
    35

ajaxfunction   15 小时 25 分钟前   ❤️ 1

吹牛皮的东西,
代码里少个换行符,
到他嘴里都能变成,代码体积减少 3%,编译速度提示 2%,运行史诗般流畅。
muzuiget
    36

muzuiget   15 小时 16 分钟前

@ajaxfunction 你泄漏天机了。
wikiwiki6
    37

wikiwiki6   14 小时 50 分钟前

swap 而已
不懂技术的又被忽悠
Huelse
    38

Huelse   13 小时 49 分钟前

真的只是 swap 吗?我记得安卓的内存机制和 linux 不一样
WebKit
    39

WebKit   13 小时 29 分钟前 via Android   ❤️ 15

不是 swap 。很多人 android 开发一点不懂,甚至连*近几代的 android 手机都没用过就开始云了。
玩儿过 android,刷过机的基本都知道写轮眼吧。这就是官方写轮眼。实在不知道你看看正在运行的进城服务跟以前有什么不同不就知道了吗
LeeReamond
    40

LeeReamond   11 小时 9 分钟前   ❤️ 9

本帖是观察米黑反科学程度的良好素材,很多人是跟事实无关的直接云,然后估摸了一个自己理解范围内的东西,然后直接开喷
fateofheart
    41

fateofheart   10 小时 56 分钟前   ❤️ 2

真的是,很多人对安卓根本就不了解,看到内存两个字就知道 swap 。。。
不过,这个“原子”内存活该被喷。。。
murmur
    42

murmur   7 小时 3 分钟前   ❤️ 5

@pengtdyd

什么叫不微创新

坚持 5v1a 不动摇?
夹层主板?
没有通话录音?
没有工作日闹钟?
NFC 不能复制卡片?

pengtdyd
    43

pengtdyd   6 小时 51 分钟前

42 楼 在监狱的小吴总是有一些狂热的追随分子,这些人常人很难理解,但是他们就是存在,很恶心人
murmur
    44

murmur   6 小时 41 分钟前   ❤️ 12

@pengtdyd 有本事这辈子苹果不要用屏下指纹、屏下相机、真全面屏,到时候我天天在 v2 看你的回复,看你是怎么看待苹果追随安卓微创新的

有些人就是跪洋人跪傻了,我话就扔着了,没小米就没安卓手机的今天,硬件不如人,软件不如人,体验再不针对优化,直接输麻了

苹果粉丝天天吹什么动画、吹那几个圆角、微创新,这是不是微精细度啊?好家伙,没有这么双标的,苹果叫工匠精神,到安卓就是无关紧要的微创新

苹果酒喜欢这种花了钱还帮着洗地的,以后中国人需要的功能统统排*后,还有大笔的苹果税奉上

x500
    45

x500   6 小时 40 分钟前

利用 hook+打桩 stub 就可以实现吧, 好久以前 miui 不是里面”借鉴”了 xp 的代码吗?
coolair
    46

coolair   6 小时 31 分钟前

跟魅族的 OneMind 样,说起来高大上,用起来坑死人的东西吧。
SenLief
    47

SenLief   6 小时 29 分钟前 via Android

应该就是 swap,oppo 还是 vivo 来着不就有,写着可以把内存 8g 扩展到 12g 。不过我还是希望有华为功能那个 app 后台常驻,不知道怎么实现的,比如知乎在某个页面切换其他 app,知乎不会重启了,好几天还在那个页面。
Building
    48

Building   6 小时 23 分钟前 via iPhone

头疼医头,脚疼医脚的典型,你说内存不够,8G12G 还不够?你说 App 流氓,你个系统连 App 都管不好?
elfive
    49

elfive   6 小时 22 分钟前 via iPhone

应该改名叫上夸克内存或者奇异夸克内存,毕竟大部分人还是知道原子并不是*小粒度
pengtdyd
    50

pengtdyd   6 小时 21 分钟前

以后多去牢里面看看小吴,聊聊一块钢板的广告之旅
nexmoe
    51

nexmoe   6 小时 20 分钟前

应该就是每个应用的不同功能有各自的进程吧,比如下图的鸿蒙 OS 中的详细信息就有不同的进程,杀掉暂时不用的进程就行了
![图片来自酷安]( https://files.catbox.moe/sw8unq.jpg)
butanediol2d
    52

butanediol2d   6 小时 13 分钟前 via iPhone

@qsmd42 可能是类似 trim 、防止写入放大之类的操作吧,叫碎片整理为了方便营销?
sexoutsex2011
    53

sexoutsex2011   6 小时 10 分钟前

实际效果应该会弱于宣传效果
Eagleyes
    54

Eagleyes   6 小时 4 分钟前

@pengtdyd #14 你说的这种事情适合于各种行业。我觉得主要问题没本事,其次是输不起。

1 、没本事,小米也要自己研发一个 HM OS ?估计没这个实力(何况这个系统也被人说套壳),另外也没人用自然就被时间淘汰了。国外强如微软 WP,2013 年听的是,三分天下,后面直接取消变成 iOS 和安卓二分天下,你凭啥认为自己有这个实力和号召力?

2 、没钱,小公司就不说了,哪怕强如 BAT,其中有像 Google X 这么个烧钱部门么?舍不得烧钱,输不起。

3 、聪明(鸡贼),做*个吃螃蟹的人自然发财,但是*大多数会变炮灰。等你研发出一个被市场证明,我在跟着学(致敬),岂不是稳扎稳打没风险?这就是你说的 Tesla 。。

非不为也,实不能也

anguiao
    55

anguiao   5 小时 58 分钟前

@pengtdyd 属于是不带“国内”两个字不会说话了。
Android 原生的很多机制并不能适应国内的应用生态,国内厂商做一些优化再正常不过了。
每家都开发一个自己的系统是不现实的,能引领潮流的企业也永远都是少数。
miaoda
    56

miaoda   5 小时 54 分钟前

![miui12.5 内存扩展]( https://cdn.jsdelivr.net/gh/WitMiao/blogPic/img/miui12.5%E5%86%85%E5%AD%98%E6%89%A9%E5%B1%95.jpg)
a22271001
    57

a22271001   5 小时 37 分钟前   ❤️ 1

内存扩展和原子内存是两个不同的东西啊喂,先区分好两个东西再发言好吧
villivateur
    58

villivateur   5 小时 35 分钟前 via Android

楼上某些人是不看题目,见到“内存”两个字就扯 swap ?杀进程跟 swap 有啥关系?
pengtdyd
    59

pengtdyd   5 小时 10 分钟前

确实优化优化 android 是属于正常不过的行为了.优化优化系统壁纸,改改字体,替换一下 GMS 框架,加些系统广告,再用一下奥氏体 304,艺术化一下,简直完美.
sockpuppet9527
    60

sockpuppet9527   4 小时 50 分钟前

歪个楼,提到“原子”,有没有可能是把 mmu 改了一下,留了一些 unmap 的内存? 不走 mmu 的内存连续且好置换,也好回收?
ZoteTheMighty
    61

ZoteTheMighty   4 小时 50 分钟前   ❤️ 10

作为一个 android 开发表示,真的有些人在自己不懂的领域张口就来,android 一个应用程序可以有多个进程,进程又分为 5 个级别,像很多通知栏的常驻通知就是一个 Foreground 进程,优先级*高,所以很多软件要求常驻通知栏来实现保活,大部分毒瘤 app 都会有多个进程,MIUI 应该就是精细管理这些进程,优先保持前台进程不被杀死。 有些人听到 swap 这个关键词就原地高潮,哦,他懂了,可是又不完全懂,可是他还想发表下高论,这样。
zpxshl
    62

zpxshl   4 小时 35 分钟前 via Android

@ZoteTheMighty 61 扯啥呢,前台进程本来就比后台进程高优,这还需要 miui 优化?
murmur
    63

murmur   4 小时 31 分钟前

@zpxshl 不一定哦,现在一些游戏允许后台下载的,这个时候你要杀前台保后台
ZoteTheMighty
    64

ZoteTheMighty   4 小时 23 分钟前

@zpxshl 建议仔细看下, 关于怎么杀进程,杀哪个操作系统会有一套逻辑判断,MIUI 魔改这一部分一点都不奇怪,各家都有魔改过。
Unclev21x
    65

Unclev21x   3 小时 59 分钟前

盖楼 60 多层。如果,我是说如果答案真如 @ZoteTheMighty 所说,那我觉得这个原子内存还是不错的,很实用。

V2 现在不管什么问题,都流行冷嘲热讽互相喷吗?骂完苹果骂华为,骂完华为骂小米。骂完小米骂苹果。

夸一个要拉另一个垫背,围魏救赵。

看的真是累啊。

Threeinchtime
    66

Threeinchtime   3 小时 38 分钟前

感觉说 swap 的根本没看这个功能描述
MrKrabs
    67

MrKrabs   3 小时 33 分钟前

就改个杀进程那不是更 low 了(
generic
    68

generic   3 小时 32 分钟前

@tyzrj766 zram? android4 就可以开…
ApmI00
    69

ApmI00   3 小时 23 分钟前

扯这么多,买个来用用不就知道啦!!!非要像一群博士吵吵万米高空一滴水的动势能。。。
tanranran
    70

tanranran   2 小时 54 分钟前

楼上至少有 80%的人在那瞎扯,回复的内容和问题毫不相关,上来就是喷。
kindjeff
    71

kindjeff   2 小时 53 分钟前 via Android

我就想问问 miui 为啥不写文档?学习鸿蒙么
liyhu
    72

liyhu   2 小时 12 分钟前

在营销厂找技术?
cairnechen
    73

cairnechen   2 小时 2 分钟前   ❤️ 1

说实话,很难发现一个比 @murmur 更令人讨厌的人,所以我一般都是站在他的对立面,不过 @pengtdyd 你做到了,赏你一个 block 名额
pengtdyd
    74

pengtdyd   1 小时 58 分钟前

@cairnechen 啥是 block 名额?
bigbigpeng3
    75

bigbigpeng3   1 小时 24 分钟前

@pengtdyd 你被他屏蔽 /拉黑了。
Lemeng
    76

Lemeng   1 小时 23 分钟前

看很多人说是 swap,如果真是,那还挺有意思的
newmlp
    77

newmlp   1 小时 2 分钟前

这不就是 swap 吗,把不活跃内存交换到磁盘上
newmlp
    78

newmlp   1 小时 0 分钟前

@tyzrj766 虚拟内存还简单?
WebKit
    79

WebKit   55 分钟前 via Android

@newmlp 并不是 swap
Bigglesworth
    80

Bigglesworth   45 分钟前

@pengtdyd #47 还有个大吴,秀波
wooody
    81

wooody   38 分钟前

大家都知道雷布斯喜欢把一些东西说的有逼格一点来吸引人,说这个功能对消费者而言是鸡肋的人的心态我是实在没想通。
一个纯技术讨论帖,知道的就发表一下意见,不知道的就听听人家的高见,或者提供下思路。
看了某人的历史发帖,不少自以为是的抖机灵,实际上对人家楼主 p 用没有,说真的我真想让 v 站发一个回复减 100 铜币。
zhouxuchen
    82

zhouxuchen   36 分钟前

@wooody #81 被你一说我好奇点了这人主页,好家伙比太平洋都水
newmlp
    83

newmlp   25 分钟前

@WebKit swap plus ,super swap,swap pro plus,原子内存。。。。。无非起个不一样的高大上的名字而已
chenrui920614
    84

chenrui920614   18 分钟前

有些人看个名字就高潮了

Android 特定用户使用时系统关机

特定用户使用时系统关机

 

wikiwiki6 · 2 小时 45 分钟前 · 472 次点击

定制设备,用户反馈用时自动关机 机器拿回,无论如何无法复现问题,换了好几台新机器还不行(电源键真的没有卡住,电池有电 让用户找了朋友测试,不关机(用户离机器 10 米距离 真的会有这种灵异事件吗? 大佬们怎么解,怎么排查

17 条回复    2021-08-13 14:37:41 +08:00

wikiwiki6
    1

wikiwiki6   2 小时 44 分钟前

难道只能请走近科学了吗
systemcall
    2

systemcall   2 小时 38 分钟前

如果是插电的东西,感觉可能是客户那边的电压的问题
还有可能是温度、湿度
tiancaixiaoshuai
    3

tiancaixiaoshuai   2 小时 24 分钟前

我遇到过相似的问题,你可以参考一下

几年前买了 vivo x510t,手机玩一段时间,再打开*品飞车的时候就会自动关机,有关机画面的那种,重新开机,再打开*品飞车,随便怎么玩,都没事

要说是内存不够,重新开机后打开多个软件,再打开*品飞车也没事,只要是重启过就一切正常,但是用一段时间,就会出问题

你可先用有问题的机器正常使用一天,再打开软件试试

wikiwiki6
    4

wikiwiki6   2 小时 4 分钟前

@systemcall 同样的环境,换个人就可以,太离谱了
wikiwiki6
    5

wikiwiki6   1 小时 57 分钟前

客户那边很生气,说我们推卸责任,但这太离谱了
est
    6

est   1 小时 10 分钟前

电磁脉冲
826540272
    7

826540272   1 小时 9 分钟前

走近科学 请
Hstar
    8

Hstar   1 小时 1 分钟前

派个人跟着客户,看他怎么用的
yfugibr
    9

yfugibr   1 小时 0 分钟前 via Android

和网络连接有关系没
goodryb
    10

goodryb   1 小时 0 分钟前

@wikiwiki6 #5 肯定是有什么因素没抓到,让客户现场重现故障

wikiwiki6
    11

wikiwiki6   29 分钟前

@goodryb 用户拍了视频,甚至手都没碰,还是有问题

wikiwiki6
    12

wikiwiki6   29 分钟前

@est 现实中有这种故障吗?
wikiwiki6
    13

wikiwiki6   28 分钟前

@yfugibr 这种问题应该跟网络没啥关系
yuancoder
    14

yuancoder   18 分钟前

这个就是用户的问题吧
since1997
    15

since1997   14 分钟前

给客户换台新的
no1xsyzy
    16

no1xsyzy   10 分钟前

奉上经典:控制变量法
你需要人员去现场严格控制变量。

其次是关机的情况是否可以暗示导致关机的物理界面,比如是电源按钮被触发,可以带示波器测量电源按钮的芯片引脚。**端的情况下,有可能是现场或者用户携带物产生的某个电磁信号被芯片误认为电源按钮被按下。

est
    17

est   7 分钟前

@wikiwiki6 有。网线、USB3 之间会相互干扰。2.4G 蓝牙之类的干扰也很多。但是对电源的干扰没具体摸过。

悬浮窗 权限

悬浮窗 权限

/**
 * 判断是有悬浮框权限
 * @return
 */
public static boolean canDrawOverlays(Context context) {
  try {
    return Settings.canDrawOverlays(context);
  } catch (NoSuchMethodError e) {
  }
}
/**
 * 判断是否缺少权限
 * @param permission
 * @return
 */
public static boolean checkSelfPermission(String permission) {
  return ContextCompat.checkSelfPermission(ApplicationContext.getInstance(), "android.permission.SYSTEM_ALERT_WINDOW") ==
      PackageManager.PERMISSION_GRANTED;
}


public static boolean checkPermission(String permission) {

  return (PackageManager.PERMISSION_GRANTED ==
      ApplicationContext.getInstance().getPackageManager().checkPermission("android.permission.SYSTEM_ALERT_WINDOW", ApplicationContext.getInstance().getPackageName()));

}


/**
 * 4.4 以上可以直接判断准确
 *
 * 4.4 以下非MIUI直接返回true
 *
 * 4.4 以下MIUI 可 判断 上一次打开app 时 是否开启了悬浮窗权限
 *
 * @param context
 * @return
 */
//OP_SYSTEM_ALERT_WINDOW=24   op = 24
public static boolean checkOp(Context context, int op) {
  final int version = Build.VERSION.SDK_INT;

  if (version >= 19) {
    AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    try {

      Class<?> spClazz = Class.forName(manager.getClass().getName());
      Method method = manager.getClass().getDeclaredMethod("checkOp", int.class, int.class, String.class);
      int property = (Integer) method.invoke(manager, op,
          Binder.getCallingUid(), context.getPackageName());

      if (AppOpsManager.MODE_ALLOWED == property) {
        return true;
      } else {
        return false;
      }
    } catch (Exception e) {

    }
  } else {

  }
  return true;
}


/**
 * 判断 悬浮窗口权限是否打开
 *
 * @param context
 * @return true 允许  false禁止
 */
public static boolean getAppOps(Context context) {
  try {
    Object object = context.getSystemService("appops");
    if (object == null) {
      return false;
    }
    Class localClass = object.getClass();
    Class[] arrayOfClass = new Class[3];
    arrayOfClass[0] = Integer.TYPE;
    arrayOfClass[1] = Integer.TYPE;
    arrayOfClass[2] = String.class;
    Method method = localClass.getMethod("checkOp", arrayOfClass);
    if (method == null) {
      return false;
    }
    Object[] arrayOfObject1 = new Object[3];
    arrayOfObject1[0] = Integer.valueOf(24);
    arrayOfObject1[1] = Integer.valueOf(Binder.getCallingUid());
    arrayOfObject1[2] = context.getPackageName();
    int m = ((Integer) method.invoke(object, arrayOfObject1)).intValue();
    return m == AppOpsManager.MODE_ALLOWED;
  } catch (Exception ex) {

  }
  return false;
}

 

Android无需权限显示悬浮窗, 兼谈逆向分析app

前言

*近UC浏览器中文版出了一个快速搜索的功能, 在使用其他app的时候, 如果复制了一些内容, 屏幕顶部会弹一个窗口, 提示一些操作, 点击后跳转到UC, 显示这个悬浮窗不需要申请android.permission.SYSTEM_ALERT_WINDOW权限.

如下图, 截图是在使用Chrome时截的, 但是屏幕顶部却有UC的view浮在屏幕上. 我使用的是小米, 我并没有给UC授悬浮窗权限, 所以我看到这个悬浮窗时是很震惊的.

%title插图%num

截图

悬浮窗原理

做过悬浮窗功能的人都知道, 要想显示悬浮窗, 要有一个服务运行在后台, 通过getSystemService(Context.WINDOW_SERVICE)拿到WindowManager, 然后向其中addViewaddView第二个参数是一个WindowManager.LayoutParamsWindowManager.LayoutParams中有一个成员type, 有各种值, 一般设置成TYPE_PHONE就可以悬浮在很多view的上方了, 但是调用这个方法需要申请android.permission.SYSTEM_ALERT_WINDOW权限, 在很多机型上, 这个权限的名字叫悬浮窗, 比如小米手机上默认是禁用这个权限的, 有些恶意app会用这个权限弹广告, 而且很难追查是哪个应用弹的. 如果这个权限被禁用, 那么结果就是悬浮窗无法展示, 比如有道词典复制查词功能, 在小米手机上经常没用, 其实是用户没有授权, 而且应用也没有引导用户给它打开授权.

现在UC能突破这个限制, 我很好奇它是怎么做到的.

研究实现

Android开发有点蛋疼的地方就是太容易被反编译, 但有时这也成为我们研究别人app的一种手段.

反编译

使用apktool可以很轻松的反编译UC.

找代码

逆向别人的app, 比较关键的地方是怎么找代码, 因为代码基本上都是混淆的, 直接看肯定是看不懂的, 只能去找, 突破口一般在字符资源上, 比如我们看到上图中的快速搜索是UC的字符, 那么我们到res/values/strings.xml去找快速搜索, 就可以找到下面的内容

<string name="dark_search_banner_search">快速搜索</string>

这里我们拿到了快速搜索对应的名字dark_search_banner_search, Android在编译时会给每个资源分配一个id, 我们grep一下这个字符资源的名字就能知道id是多少, 一般在R.javares/values/public.xml中有定义, 我直接到public.xml中找到了它的id

<public type="string" name="dark_search_banner_search" id="0x7f070049" />

有了字符资源的id 0x7f070049, 我们再在代码里面grep一下这个id, 就能知道哪几个文件使用了这个字符资源.

之所以这么确定是在代码里, 是因为UC在我们复制的内容不同时, 悬浮窗标题会不一样, 一定是在代码里控制的, 结果如下

./com/uc/browser/b/f.smali

结果可能和大家不一样, 但是一定会找到一个被混淆的smali文件

看代码

这一部应该是*恶心的. smali代码和java代码的关系, 就像汇编代码和C++代码, 但是smali比汇编代码要容易理解的多, 不然也不会有那么多公司故意将代码写在C++层了.

虽然代码都被混淆了, 而且以我们不熟悉的方式出现, 但我们可以根据一些蛛丝马迹来判断代码的执行, 比如Framework的类和API是不能被混淆的, 这也是我们能看懂smali的原因之一, 我们可以结合这些面包屑来还原整个app代码, 当然这需要我们对smali很熟悉, 如果不熟悉smali, 至少要对Android的API熟悉. 因为有时实在看不懂, 我们要靠猜来还原一段代码的逻辑.

首先在代码里面找到0x7f070049, 发现了如下代码

    (省略)
    const v3, 0x7f070049

    invoke-virtual {v1, v3}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String;

    move-result-object v1

    iput-object v1, v0, Lcom/uc/browser/b/a;->dpC:Ljava/lang/String;

    :cond_9

    (省略)

    invoke-virtual {v0, v1}, Lcom/uc/browser/b/a;->o(Landroid/graphics/drawable/Drawable;)V
    :try_end_2
    .catch Ljava/lang/Exception; {:try_start_2 .. :try_end_2} :catch_0

    goto/16 :goto_0
    (省略)

这是0x7f070049出现之后的一部分代码, 一路看下来, 其实都是在取值赋值, 就拿0x7f070049来说:

#使v3寄存器的值为0x7f070049
    const v3, 0x7f070049
#v1是Resources实例, 调用它的getString方法, 方法的参数是v3中的值
    invoke-virtual {v1, v3}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String;
#将结果存入v1寄存器
    move-result-object v1

其实就是我们常用的getResources().getString
其实如果一直这么看下去, 会发现毫无头绪, 剩下的代码一直在干差不多的事情, 所以我只截取了这部分, 注意*后一行

goto/16 :goto_0

也就是说, 有可能代码转到goto_0那儿去了, 那么看看goto_0那里又写了些什么

    :goto_0
    (省略)

    const-string v1, "window"

    invoke-virtual {v0, v1}, Landroid/content/Context;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;

    move-result-object v0

    check-cast v0, Landroid/view/WindowManager;

    invoke-interface {v0}, Landroid/view/WindowManager;->getDefaultDisplay()Landroid/view/Display;

    move-result-object v0

    invoke-virtual {v0}, Landroid/view/Display;->getWidth()I

    move-result v0

    iget-object v1, v10, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    iput v0, v1, Landroid/view/WindowManager$LayoutParams;->width:I

    iget-object v0, v10, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    invoke-virtual {v10}, Lcom/uc/browser/b/a;->getContext()Landroid/content/Context;

    move-result-object v1

    invoke-virtual {v1}, Landroid/content/Context;->getResources()Landroid/content/res/Resources;

    move-result-object v1

    const v2, 0x7f0d0022

    invoke-virtual {v1, v2}, Landroid/content/res/Resources;->getDimension(I)F

    move-result v1

    float-to-int v1, v1

    iput v1, v0, Landroid/view/WindowManager$LayoutParams;->height:I

    iget-object v0, v10, Lcom/uc/browser/b/a;->mWindowManager:Landroid/view/WindowManager;

    iget-object v1, v10, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    invoke-interface {v0, v10, v1}, Landroid/view/WindowManager;->addView(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V

其实看到const-string v1, "window", 我们就应该有所警惕了, 这可能是关键代码了. 为什么这么说? 因为悬浮窗的实现里面, 需要获取WindowManager, 从而需要调用Context.getSystemService(Context.WINDOW_SERVICE), 而官方文档写了Context.WINDOW_SERVICE就是常量window. 而后我们看到代码中构造了WindowManager.LayoutParams, *终在addView时传入.

看到这里, 我也觉得很奇怪, 我在悬浮窗原理中写的是我知道的实现悬浮窗的方法, UC的实现好像跟我调用的是相同的API, 也没看到反射之类可能展示奇技淫巧的代码, 为什么UC就可以不需要权限直接显示悬浮窗呢?

猜测

我认为addView的第二个参数WindowManager.LayoutParams可能是关键, 所以我需要知道UC是如何构造这个WindowManager.LayoutParams的.

由于是系统的类, 无法混淆, 直接搜索LayoutParams就找到了下面的代码

iget-object v1, v10, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

这句话就是把v10的值赋给v1v10com/uc/browser/b/a的成员dpx, 那么打开com/uc/browser/b/a.smali看看dpx到底是怎么构造的.

    (省略)

.field dpx:Landroid/view/WindowManager$LayoutParams;

    (省略)
    .line 68
    new-instance v0, Landroid/view/WindowManager$LayoutParams;

    invoke-direct {v0}, Landroid/view/WindowManager$LayoutParams;-><init>()V

    iput-object v0, p0, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    .line 69
    if-eqz p2, :cond_0

    .line 70
    iget-object v0, p0, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    const/16 v1, 0x7d5

    iput v1, v0, Landroid/view/WindowManager$LayoutParams;->type:I

    .line 74
    :goto_0
    iget-object v0, p0, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    const/4 v1, 0x1

    iput v1, v0, Landroid/view/WindowManager$LayoutParams;->format:I
    (省略)

这里的代码就很简单的, 我*先看的是下面这段

    const/16 v1, 0x7d5

    iput v1, v0, Landroid/view/WindowManager$LayoutParams;->type:I

这两句代码就是把WindowManager.LayoutParams.type字段设成0x7d5, 官网上写了0x000007d5是WindowManager.LayoutParams.TYPE_TOAST的值.

验证

实际测试了一下, 将type设置成TYPE_TOAST果然有奇效, 不需要android.permission.SYSTEM_ALERT_WINDOW权限就能显示一个悬浮窗.

之前我一直以为调用了系统WindowManager.addView需要android.permission.SYSTEM_ALERT_WINDOW权限, 但实际上调用这个方法是不需要权限的, 在Android源码中有这么一段

public int checkAddPermission(WindowManager.LayoutParams attrs) {
    int type = attrs.type;

    if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
            || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
        return WindowManagerImpl.ADD_OKAY;
    }
    String permission = null;
    switch (type) {
        case TYPE_TOAST:
            // XXX right now the app process has complete control over
            // this...  should introduce a token to let the system
            // monitor/control what they are doing.
            break;
        case TYPE_INPUT_METHOD:
        case TYPE_WALLPAPER:
            // The window manager will check these.
            break;
        case TYPE_PHONE:
        case TYPE_PRIORITY_PHONE:
        case TYPE_SYSTEM_ALERT:
        case TYPE_SYSTEM_ERROR:
        case TYPE_SYSTEM_OVERLAY:
            permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
            break;
        default:
            permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
    }
    if (permission != null) {
        if (mContext.checkCallingOrSelfPermission(permission)
                != PackageManager.PERMISSION_GRANTED) {
            return WindowManagerImpl.ADD_PERMISSION_DENIED;
        }
    }
    return WindowManagerImpl.ADD_OKAY;
}

可以猜到这个方法是往系统的WindowManageraddView的时候做权限检查用的, 那个type就是我们在构造WindowManager.LayoutParams时赋值的type, 可以看到, 除了TYPE_TOAST, 其他都是要权限的, 而且非常喜感的是, 代码中的注释还说他们现在对这种type毫无限制, 应该引入标记来限制开发者.

处理兼容性

在这篇文章刚刚公布的时候, 就有同学反馈悬浮窗无法接收事件, 刚开始我并没有特别在意, 在廖祜秋大神做了一个demo之后, 这篇文章阅读量又涨了不少, 随即收到更多反馈事件的问题, 我今天晚上借了台MIUI V5 4.2.2实测了一下, 这台机器上UC的快速搜索功能也无法正常使用.

在这个ROM上表现为:
使用TYPE_PHONE这类需要权限的type时, 只有在app处于前台时能显示悬浮窗, 且能正常接受触摸事件. 如果在应用详情里面授悬浮窗权限, 则工作完全正常.
(这里是MIUI V5对悬浮窗的特殊处理, 现在的ROM, 包括MIUI V6上, 如果不授权, 无法显示任何悬浮窗)
使用TYPE_TOAST这个不需要权限的type时, 悬浮窗正常显示, 但不能接受触摸事件.

我重新检查了一下smali代码, 发现UC是有分版本处理的, 不过因为smali代码的规则问题, 很难直接看出来, 我把分析过程写出来, 顺便解释一下smali的语法, 供大家以后逆向时拿来参考.

这次我是在OS X上反编译的, 所以变量名可能略有区别.

接着上面com/uc/browser/b/a.smali中查看dpx的构造过程, 代码如下:

.field dpx:Landroid/view/WindowManager$LayoutParams;

(省略)

# direct methods
.method public constructor <init>(Landroid/content/Context;Z)V
    .locals 7

    (省略)

    .line 68
    new-instance v0, Landroid/view/WindowManager$LayoutParams;

    invoke-direct {v0}, Landroid/view/WindowManager$LayoutParams;-><init>()V

    iput-object v0, p0, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    .line 69
    if-eqz p2, :cond_0

    .line 70
    iget-object v0, p0, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    const/16 v1, 0x7d5

    iput v1, v0, Landroid/view/WindowManager$LayoutParams;->type:I

为了方便说明, 我遵循smali的规则, 它用.line XX, 我们就说这是第XX行的代码.

上面是我之前分析得到UC使用的是TYPE_TOAST的地方, 证据就是第70行的const/16 v1, 0x7d5, 但是要知道, smali代码没有跳转的话, 就是从上往下执行, 我们看第69行的代码如下:

.line 69
if-eqz p2, :cond_0

这句话的意思是如果p2等于0, 控制流跳转到cond_0, 否则就是继续顺序往下执行. 也就是说UC只有在p2 != 0条件满足的时候才会使用TYPE_TOAST, 我们看看cond_0对应的代码.

    .line 72
    :cond_0
    iget-object v0, p0, Lcom/uc/browser/b/a;->dpx:Landroid/view/WindowManager$LayoutParams;

    const/16 v1, 0x7d2

    iput v1, v0, Landroid/view/WindowManager$LayoutParams;->type:I

这里很简单, 就是将0x7d2赋给了type, 官网写了0x000007d2TYPE_PHONE, 也就是说UC在某种情况下还是会用需要权限的老方法展示悬浮窗.

现在问题是条件是什么, 关键在p2, 在smali里面, 有两种寄存器命名规则, 一种叫v命名规则, 另一种是p命名规则, 当然只是命名规则而已, 在使用apktool时是可以选的. 这里是p命名规则.

我刚才分析的赋值过程, 所在的方法是下面这个, 我在刚才的代码片段中也保留了这个部分.

# direct methods
.method public constructor <init>(Landroid/content/Context;Z)V
    .locals 7

这就是com/uc/browser/b/a的构造方法, dpx就是在构造方法里初始化的, .locals 7告诉我们这个方法中将出现7个局部寄存器(local register), 名字是v0, v1…v6, 而这个方法的参数有3个, 隐式告诉我们这个方法中将出现3个参数寄存器(parameter register), 名字分别是p0, p1, p2.

我是怎么知道这个方法有3个参数的呢. smali中非静态方法, 都隐含一个参数p0, 指向自身, 和Java中的this是一个意思, 而方法的参数写在括号里, 也就是Landroid/content/Context;Z, 其中Landroid/content/Context;很明显就是Android中的Context, 值存储在p1里, 而Z对应的是Android中的boolean, p2就是他了.

也就是说, type是用TYPE_TOAST还是用TYPE_PHONE, 取决于这个构造方法的第二个参数, 那到底谁构造了com/uc/browser/b/a呢? 可以去代码里面搜形如new-instance ***, Lcom/uc/browser/b/a;的代码. 更保险的做法是搜Lcom/uc/browser/b/a然后一个一个的看.

我在com/uc/browser/b/f.smali里面找到了下面的代码:

    .prologue
    const/4 v0, 0x0

    const/4 v1, 0x1

    (省略)

    new-instance v3, Lcom/uc/browser/b/a;

    iget-object v4, v9, Lcom/uc/browser/b/e;->mContext:Landroid/content/Context;

    sget v5, Landroid/os/Build$VERSION;->SDK_INT:I

    const/16 v6, 0x13

    if-lt v5, v6, :cond_0

    move v0, v1

    :cond_0
    invoke-direct {v3, v4, v0}, Lcom/uc/browser/b/a;-><init>(Landroid/content/Context;Z)V

这段代码首先是创建了com/uc/browser/b/a的实例, 存储在v3中, 从另一处拿到了一个Context存储在v4中, 然后拿到了当前系统的android.os.Build.VERSION.SDK_INT存储在v5中, 此时将v6的值设为0x13, 千万别粗心看成13了, 我好几次都觉得这是13, 其实是十进制的19, 接下来是一个条件分支, 如果v5的值小于v6, 也就是说android.os.Build.VERSION.SDK_INT < 19, 直接跳转到cond_0, 否则先将v1的值赋给v0, 再顺序执行.

这句代码

invoke-direct {v3, v4, v0}, Lcom/uc/browser/b/a;-><init>(Landroid/content/Context;Z)V

就是调用v3的构造方法, 参数是v4和v0, 分析一下上面这段代码的逻辑就是:
如果当前系统API level小于19, 那么第二个参数就是0, 否则就是1.

而这第二个参数的值就是之前我们分析的p2的值, UC只有在p2 != 0条件满足的时候才会使用TYPE_TOAST, 把整个逻辑串起来就是:

UC在API level >= 19的时候, 使用TYPE_TOAST, 其他情况使用TYPE_PHONE(需要权限).

可能是为了规避在低版本TYPE_TOAST不能接受事件的问题.

 

实测效果

我之前写的一个app有悬浮窗播放功能, 支持拖动窗口和点击暂停, 关闭窗口等等, 在4.4.4上实测功能正常.

%title插图%num

无权限悬浮窗演示gif

感谢微博上关注的大神廖祜秋, 他做了个demo, 虽然交互和UC不同, 可以参考一下实现.

%title插图%num

廖祜秋大神的demo

关于这个, 他也写了一篇Android 悬浮窗的小结

其他补充

评论区的浮海大虾同学有更多补充如下:

TYPE_TOAST一直都可以显示, 但是用TYPE_TOAST显示出来的在2.3上无法接收点击事件, 因此还是无法随意使用.
下面是我之前研究后台线程显示对话框的时候记得笔记, 大家可以看看我们项目中有需求需要在后台任务中显示Dialog, 项目*初的做法是用Activity模拟Dialog, 一个Activity已经承载了近20种Dialog, 代码混乱至*. 后来我发现Dialog可以通过改变Window Type实现不依赖Activity显示, 然后就很兴奋的要在使用这种方式来作为新的实现方式.
*初WindowType是WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 可是这是悬浮窗了, MIUI会默认禁止(真他妈操蛋,也没有任何提示)*终放弃. 后来试着换成了WindowManager.LayoutParams.TYPE_TOAST, 起初效果很好,MIUI也不禁止了, 哪里都能显示, 这下开心了. 可是后来又发现在2.3上不能接收点击事件, 也就是说Dialog上的按钮不能点击, 这他妈就很操蛋了, 又放弃了. 又试了试其他的Type都不能满足需求, 结果如下:TYPE_SEARCH_BAR: 未知
TYPE_ACCESSIBILITY_OVERLAY: 拒*使用
TYPE_APPLICATION: 只能配合Activity在当前APP使用TYPE_APPLICATION_ATTACHED_DIALOG: 只能配合Activity在当前APP使用
TYPE_APPLICATION_MEDIA: 无法使用(什么也不显示)
TYPE_APPLICATION_PANEL: 只能配合Activity在当前APP使用(PopupWindow默认就是这个Type)
TYPE_APPLICATION_STARTING: 无法使用(什么也不显示)
TYPE_APPLICATION_SUB_PANEL: 只能配合Activity在当前APP使用TYPE_BASE_APPLICATION: 无法使用(什么也不显示)
TYPE_CHANGED: 只能配合Activity在当前APP使用
TYPE_INPUT_METHOD: 无法使用(直接崩溃)
TYPE_INPUT_METHOD_DIALOG: 无法使用(直接崩溃)
TYPE_KEYGUARD_DIALOG: 拒*使用
TYPE_PHONE: 属于悬浮窗(并且给一个Activity的话按下HOME键会出现看不到桌面上的图标异常情况)
TYPE_TOAST: 不属于悬浮窗, 但有悬浮窗的功能, 缺点是在Android2.3上无法接收点击事件
TYPE_SYSTEM_ALERT: 属于悬浮窗, 但是会被禁止

尾声

现在我们都知道了如何在不申请权限的情况下显示悬浮窗, 我相信以中国Android开发者的脑洞, 一定会有很多有趣或恶心的功能被开发出来, 一方面我自己觉得这个东西很有用, 可以实现一些很神奇的功能, 另一方面又担心这个API被滥用, *终不得不限制权限.

还有就是, 逆向分析仅用于学习

 

浮窗WindowManager view返回和Home按键事件监听

出于功能需求,需要在所有的view之上显示浮窗,于是需要在WindowManager的View上处理返回键的响应,

mFloatingWindowView =  layoutInflater.inflate(R.layout.floating_window, null, false);


mFloatingWindowLayoutParams = new WindowManager.LayoutParams();
  // 设置window type
        mUserConversationWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;

        mUserConversationWindowParams.format = PixelFormat.TRANSLUCENT;// 设置图片格式,效果为背景透明

        // 设置Window flag
        mUserConversationWindowParams.flags =
                //可使用FLAG_DISMISS_KEYGUARD选项直接解除非加锁的锁屏状态。此选项只用于*顶层的全屏幕窗口。
                WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL   //必须  设置窗口不拦截窗口范围之外事件
                    
                         |WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH  // 必须  设置在有FLAG_NOT_TOUCH_MODAL属性时,窗口之外事件发生时自己也获取事件

                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
mWindowManager.addView(mFloatingWindowView, mFloatingWindowLayoutParams);

这里千万要注意不能用WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,我就是死在这上面的,如果设置成FLAG_NOT_FOCUSABLE,死都收不到返回键的事件的!

 

import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.LinearLayout;

/**
 * Created by KB-Shirlman on 4/26/2016.
 */
public class FloatingWindowView extends LinearLayout {
    public FloatingWindowView(Context context) {
        super(context);
    }

    public FloatingWindowView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FloatingWindowView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                || event.getKeyCode() == KeyEvent.KEYCODE_SETTINGS) {
if(event.getAction()==KeyEvent.ACTION_DOWN){   //按键  按下和移开会有两个不同的事件所以需要区分
          closecao();   //点击返回 要执行的方法
}
} return super.dispatchKeyEvent(event); }  }

 

floating_window.xml

下面附赠哪都能搜索的到的WidnowManager Home按键监听。

打开浮窗时调用:

关闭浮窗时调用: