-
鸿蒙 OS 的诞生,不是为了替代 Android,而是超越 Android,打造万物互联时代的下一代操作系统。华为消费者业务软件部总裁王成录在 16 日的鸿蒙 OS 手机开发者 Beta 版发布会上激动地说。自 2019 年对外发布以来,鸿蒙 OS 一直吸引着外界的目光。其中有支持,也不乏质疑。华为并不是第一个自研手机 OS 的国产企业,却被聚光灯照在身上最多。在面向开发者推出鸿蒙 OS 的手机 Beta 版之后,新浪科技获悉,明年一季度发布的华为 P50 将正式搭载鸿蒙 OS,明年华为手机以及其它自研设备也将全面升级鸿蒙 OS。不过,用户升级鸿蒙 OS 之后,手机将仍然能够兼容和运行 Android App,以留出过渡期。而等待鸿蒙 OS 生态成熟后,华为将全面向鸿蒙切换。兼容 Android 不同于 Android在发布会现场,新浪科技也见到了为演示鸿蒙 OS 特性而展出的已经升级鸿蒙 OS 的华为手机。从体验上来看,这款手机在操作习惯、界面设计等方面与目前华为基于 Android 开发的 EMUI 区别不大。并且在内置的华为应用商店中,也可以自由下载和运行 Android App。这也引发了一些网友争议:「是不是就是 Android 系统改个壳?」一位现场工作人员向新浪科技表示,演示机只是为了展示基于鸿蒙 OS 的分布式能力,未来正式版的鸿蒙 OS 在手机上肯定会有全新的界面设计。实际上,从华为相关技术专家以及现场展示的功能上来看,鸿蒙 OS 与 Android 系统确实有着诸多差异化。王成录认为,过去近 20 年基于手机的移动互联网生态发展迅速,但无论是手机的发货量还是移动 App 的数量,以及用户在手机上消耗的时间,从 2018 年开始就不再增长,甚至在近两年走向下降。这意味着基于手机的生态已经来到了一个临界点,他判断,未来是 IoT 的时代。但在 IoT 设备数量快速增长的同时,仍然面临很多问题。目前所有的应用生态几乎全部基于智能手机平台。智能手表、智能电视、车机等 IoT 设备的生态发展非常缓慢,「很多人家里面很可能都有几台音箱,但是这些音箱用了一周,最多两周可能就会被遗忘了。这背后的原因是音箱上的应用太少了,如果我们解决不了这个问题,IoT 的时代是不可能真正来临的。」在王成录看来,IoT 生态发展缓慢最核心的原因就是操作系统的高度碎片化。即使是同一家企业生产的 IoT 设备之间连接、配网、使用都非常困难,更不用说不同企业生产的不同 IoT 设备。每个 IoT 设备的系统不同、应用不同,开发者面临诸多困难,自然应用数量也就少得可怜。王成录多次对外强调,鸿蒙 OS 的诞生,不是为了替代Android,而是超越Android,打造万物互联时代的下一代操作系统。在现场展区,华为展示了智能家居、互动娱乐、泛终端社交购物、移动办公跨端接续、智慧教育、智慧出行、运动健康这七大鸿蒙 OS 的新应用场景。以泛终端社交购物为例,据京东零售产品总监王志强介绍,与 Android 版本相比,鸿蒙版本年的京东 App 可以解决诸多目前的购物痛点。比如在购物比价时,消费者不再需要频繁切换产品页面,可以将产品详情页直接流转至平板上,手机和平板可以同时对比不同的商品;在直播购物场景下,可以将直播流转至智慧屏上,手机则被释放出来;在拼单场景下,好友或者家人可以共享屏幕讨论商品,甚至共享购物车一起拼单凑满减,并且各自生成订单,各自结算付款。在移动办公方面,科大讯飞消费者事业群听见科技 CTO 苏文畅介绍,科大讯飞的录音笔搭载鸿蒙 OS 之后,手机一碰即用,无需下载 App;碰一碰还可以将录音文件快传至手机,甚至可以将实时转写跨设备流转,手机端的实时转写可以流转至智慧屏端实时显示。从现场演示的案例来看,鸿蒙 OS 确实推出了一些 Android 并未实现、或者实现起来颇为复杂的功能。并且与 Android 系统以手机为主相比,手机只是鸿蒙 OS 目标设备中的一部分,手机+IoT 设备在功能、交互等方面的互联互通,才是鸿蒙 OS 的核心目标所在。构建生态 迈出第一步王成录坦言,做一个操作系统,技术上不难,生态才是核心。生态涉及的广度、深度和复杂度远远超过所有的单个技术。另外,如果配合不上产业发展变现的机会,强做生态也非常难成功。发布的第二年,鸿蒙 OS 的落地仍然处于早期阶段。对于一个处于商业化前期的 OS 而言,要吸引企业和个人开发者投入人力、物力开发新应用,极为不易。以京东为例,要实现上述不同于 Android 版本的新功能,开发者需要基于鸿蒙 OS 的开发者工具单独开发一个版本,也即是说,虽然鸿蒙 OS 能兼容 Android App,但企业需要同时开发和维护 Android 版本和鸿蒙 OS 版本的 App。据京东零售产品总监王志强透露,在鸿蒙版本的京东 App 开发中,京东方面投入了包括项目团队、产品团队和研发团队在内的 26 人;华为方面也投入了 10 人以上的技术合作和支持团队。在王成录的演讲中,京东也被当做典型案例分享。他表示,有了鸿蒙 OS,京东购物的应用就可以有手机以外更多的设备入口,可以在冰箱上、电视上,甚至所有带屏、带音响、带触控的亿级设备上运行。这对于寻求增量用户和场景的京东而言,无疑具备巨大的吸引力。但华为也遇到了一些阻力,其中就有企业曾参与为鸿蒙 OS 开发 App,中途因为人力投入等原因又转而放弃。另外,生态的建设也非一日之功。在现场展示的互动娱乐案例中,华为与优酷联合开发了多项跨屏互动新功能。其中手机端可以在 150°范围内自由操控平板端的视频观看角度,不过这一方面需要专门制作这类片源,另外由于计算方式的差异,手机与智慧屏还未实现该功能,双方目前正在开展联合研究。为了激励企业和个人开发者加入,华为也推出了一系列措施。由于 IoT 设备品类繁多且操作系统不同,开发者需要为手机、平板、手表等不同设备重复开发应用,且不同尺寸屏幕的设计和交互适配困难。而华为此次提供了一系列构建全场景应用的完整框架和开发工具平台,帮助开发者实现了一次开发多端部署,分布式的 UI 框架也能够让应用布局自适应多种屏幕尺寸。华为还宣布启动鸿蒙 OS 开发者创新大赛,将通过 150 万元奖金、20 位专业导师指导激发更多创新应用诞生。根据华为方面公布的数据,目前已有京东、银联、优酷、科大讯飞等 120 多家企业开始基于鸿蒙 OS 进行开发;超过 10 万开发者已参与华为赋能活动,为鸿蒙 OS 生态建设做贡献;接下来,华为也将在上海、广州等地继续举办开发者日活动,向开发者分享鸿蒙 OS 开发技术和应用案例。鸿蒙 OS 手机 何时问世?虽然华为一直对外强调,鸿蒙 OS 是面向 IoT 设备而生。但在谷歌 GMS 持续断供之下,华为手机何时搭载鸿蒙 OS,成为外界关注的焦点。华为消费者业务软件部副总裁杨海松透露,按照目前的进度,明年所有华为自研设备都将升级鸿蒙 OS,消费者不需要购买新的设备体验鸿蒙系统。同时,明年华为也将发布基于鸿蒙 OS 的智能手机。新浪科技从知情人士处获悉,明年一季度华为手机将正式搭载鸿蒙 OS,华为 P50 上市时会全面搭载鸿蒙 OS。另外,明年华为手机搭载鸿蒙 OS 之后,会采用双架构,仍然兼容 Android App,但要体验鸿蒙 OS 差异化的分布式特色功能,就需要安装鸿蒙版本的 App。「可能会单独开设鸿蒙 OS 的应用专区,留一个过渡期,让开发者逐步迁移,也是照顾用户的使用体验」,该人士说,等待鸿蒙 OS 生态成熟后,华为将进行全面切换。不过,从华为展示的鸿蒙 OS 的新功能来看,单单手机端搭载鸿蒙 OS 远远不够,在更多 IoT 设备上应用鸿蒙 OS,这些功能才能在端到端之间实现。今年双 11,就有九阳、美的、老板电器的多款搭载鸿蒙 OS 的 IoT 设备开售。根据王成录公布的计划,鸿蒙 OS 明年要覆盖 40+主流品牌 1 亿台以上的设备。此前华为消费者业务 CEO 余承东也公布过鸿蒙 OS 的开源计划,将在 2021 年 4 月面向内存 128MB-4GB 的终端设备开源;2021 年 10 月以后将面向 4GB 以上所有设备开源。如果华为的计划顺利推进,可以预见的是,明年鸿蒙 OS 的生态也将迎来新的发展阶段。「我个人非常有信心,也希望把这个信心传递给中国所有移动互联网产业的从业人员。」王成录说,中国网络最好、IoT 模块制造能力全世界最强、应用创新全世界最强、从业者全世界最多、市场全世界最大,在未来 IoT 的时代,中国企业有望开创一个全新的世界。
-
在鲲鹏服务器上使用android delete avd -n test_7android create avd --name test_7 --target android-24 --abi arm64-v8a --device "Nexus 4" --skin 720x1600 --forceemulator -avd test_7 -skip-adb-auth -no-window -cores 4 -writable-system -partition-size 16384 -verbose -gpu host -qemu -enable-kvm -m 8192 -vnc :86 创建云手机后,如何调试android 模拟器的代码
franklinshao 发表于2020-12-16 17:26:17 2020-12-16 17:26:17 最后回复 franklinshao 2020-12-16 17:26:17
5135 0 -
【移动应用开发全栈成长计划】Android入门篇•最终考核打卡帖打卡已结束,考核结果正在统计中不知不觉中,移动应用开发全栈成长计划已与大家见面一个月的时间了,所有课程内容都已经全部更新完毕。大家积极的学习态度,遇到问题及时在学习群内提出,让本阶段全栈课程可以顺利完成再次感谢大家:◎积极完成每章的随堂测验打卡,做到了课后的知识强化与巩固;◎认真完成每周读书笔记打卡,将自己的学习心得总结下来;◎有活力地问答官打卡,分享自己在学习中的问题和经验。十分感谢大家能顺利完成第一阶段的学习内容,我们也在大家学习的过程中,总结了优缺点,让大家可以做一个全能型移动端开发者。所以,对下阶段课程作出调整和更新,敬请期待哦~~~现在,大家迎来了第一阶段考核,让我们来看一下考核的具体内容▶考核打卡时间:2020.12.08-2020.12.20 23:59 ▶考核途径:点击下方链接,选择【Android入门篇考核作业】https://classroom.devcloud.huaweicloud.com/classdetail/697ea02042c44116967185f87768b75a/job▶考核要求:进入考核页面后,点击“查看习题描述”,详细阅读考核要求和评判标准后按要求进行考核,提交机会有2次,请大家认真作答。▶打卡要求:由于本阶段涵盖知识点比较多,所以上传形式为按考核要求在本地编辑器运行后,将压缩包上传至classroom后台,并提交。并且按以下要求进行截图打卡!只有在按照要求进行打卡才会得到第一阶段考核证书!只有在按照要求进行打卡才会得到第一阶段考核证书!只有在按照要求进行打卡才会得到第一阶段考核证书!▶打卡方式:方式:***正确的回复格式:华为云账号+姓名(显示在考核证书上面名字)+提交完考核页面截图1张华为云ID:grandmaster 姓名:华为云小助手01重要提示:请严格按照回复示例进行回复,本次为阶段末考核项目,如果没有按照要求的格式进行回复,版主将不予提示,同时不计入考核结果,会影响考核证书及奖品的发放哦~▶考核评分:提交考核内容后由专家老师根据评分标准评分,满分100分,分数将于开始审核后15个工作日内公布,分数会公布在博客里面,具体请大家留意小助手信息。▶评分标准:1、项目整体编译无报错、运行效果流畅2、页面与华为云APP登录页越接近,得分越高3、代码书写越规范,得分越高4、扩展越丰富,得分越高▶考核奖励:◎参与最后考核并按要求回复本帖,就可得到电子版证书(证书上会根据大家的回复的真实姓名填写信息,请大家在留信息时注意)参与考核,人人有份,证书由1号小助手微信点对点发放,没添加小助手企业微信的伙伴可以扫描下方二维码添加,证书将在第一阶段结束后15个工作日内发放,请大家耐心等待小助手的通知哦~(注意:凭各阶段电子证书最后可兑换实体证书哦~)◎考核分数≥60分并回复本帖,另外奖励华为云定制敏捷扑克牌(数量有限,先到先得,按回帖时间发放,占楼无效!)◎本阶段会有专家老师评审出1位“最佳代码”(提交代码分数最高,同分看打卡回帖提交时间)获奖者,还会额外得到华为云无线鼠标哦~◎特别提示:参加了移动应用开发所有阶段考核的同学们,最后可凭每阶段证书兑换整阶段实体证书一份,请大家关注后续规则! ◎参与考核即可获得20积分累计到总积分中,赢取最后积分大奖;大家别忘了随堂测验,读书笔记和问答官排位赛回复打卡截止日期为12月20日23:59,抓紧时间打卡呀~最佳问答官还可能得到华为云定制书包哦~积分排行细则积分排行榜奖品全阶段累计积分奖励活动注意事项1.由于本帖回复内容为阶段考核测试内容,并涉及到个人隐私,已设置回帖仅版主可见,请大家放心回复2.请大家务必在考核规定时间12月20日 23:59内完成考核回帖打卡,否侧将影响证书和奖品的发放3.积分和考核奖品信息我们会在考核阶段结束后15个工作日内整理完毕,发放奖品
-
亲爱的开发者们大家心心念念的【移动应用开发全栈成长计划】已开课我们也特别为大家设置了【学习任务打卡】环节为的就是让大家巩固学习成果,紧跟学习进度请将需要完成的每周学习笔记按要求回复到本帖下方按要求格式回复即可获得积分累计阶段奖品,还能有机会获得附加幸运奖哦~征集时间2020.11.16-2020.12.17 23:59征集要求在本帖中,回复自己本周课程内容的学习笔记回复格式:华为云ID+第几周笔记+笔记内容,并分享些读书心得(字数≥200字)示例图如下:奖励方式每周每篇有效笔记可获得5积分阶段学习将以积分排行榜的形式,对前300名小伙伴进行奖励哦!此外还有附加奖励,每周在本周内提交学习笔记的用户中,抽取10位幸运奖奖励华为云定制文件收纳包 保温杯已供不应求,我们的奖品暂时更换成文件收纳包哦~各阶段积分排行榜奖品三个阶段总积分排行榜奖品 活动注意事项1. 学习任务提交后,小助手会在本阶段学习周期内,按序完成审核,并增加活动积分;2. 本次活动通过完成提交学习笔记任务,可获得的积分上限为5积分/每周;3. 请务必按照上述要求提交内容,以免影响积分增加;4. 若积分值相同则以完成学习任务的时间先后排序,其中任务完成时间的判定优先级为:阶段考核>问答官>分享转发>每周学习笔记>每章随堂测验;5. 其他积分获取方式请查看活动社群公告。想了解更多关于全栈成长计划课程内容请移步主帖:https://bbs.huaweicloud.com/forum/thread-84766-1-1.html除了本帖任务,其他学习任务可以通过以下链接进行查看:查看随堂测验打卡帖:https://bbs.huaweicloud.com/forum/thread-87346-1-1.html查看问答官排位打卡帖:https://bbs.huaweicloud.com/forum/thread-87342-1-1.html
-
亲爱的开发者们大家心心念念的【移动应用开发全栈成长计划】已开课我们也特别为大家设置了【学习任务打卡】环节为的就是让大家巩固学习成果,紧跟学习进度请将需要完成的每章随堂测验按要求回复到本帖下方按要求格式回复即可获得积分累计阶段奖品,还能有机会获得附加幸运奖哦~征集时间2020.11.16-2020.12.17 23:59征集要求在本帖中,回复自己本章随堂测验内容打卡要求在本帖中,回复对应章节的随堂测验并提交截图 ↓章节作业位置:打卡回复格式:华为云ID+课程完成截图,如图所示↓↓↓华为云ID:grandmaster奖励方式每周每篇有效笔记可获得2积分阶段学习将以积分排行榜的形式,对前300名小伙伴进行奖励哦!此外还有附加奖励,每周在本周内提交学习笔记的用户中,抽取10位幸运奖奖励华为云定制敏捷扑克牌 各阶段积分排行榜奖品三个阶段总积分排行榜奖品 活动注意事项1. 学习任务提交后,小助手会在本阶段学习周期内,按序完成审核,并增加活动积分;2. 本次活动通过完成提交学习笔记任务,可获得的积分上限为2积分/每章;3. 请务必按照上述要求提交内容,以免影响积分增加;4. 若积分值相同则以完成学习任务的时间先后排序,其中任务完成时间的判定优先级为:阶段考核>问答官>分享转发>每周学习笔记>每章随堂测验;5. 其他积分获取方式请查看活动社群公告。想了解更多关于全栈成长计划课程内容请移步主帖:https://bbs.huaweicloud.com/forum/thread-84766-1-1.html除了本帖任务,其他学习任务可以通过以下链接进行查看:查看每周读书笔记打卡帖:https://bbs.huaweicloud.com/forum/thread-87350-1-1.html查看问答官排位打卡帖:https://bbs.huaweicloud.com/forum/thread-87342-1-1.html
-
亲爱的开发者们大家心心念念的【移动应用开发全栈成长计划】已开课我们也特别为大家设置了【学习任务打卡】环节为的就是让大家巩固学习成果,紧跟学习进度现推出【问答官排位赛】,请各位同学详细查看本帖说明按要求格式回复即可获得积分累计阶段奖品,还能有机会获得附加幸运奖哦~ 活动时间:2020.11.16-2020.12.17 23:59 参与方式:用户在本帖里发布自己在学习移动端技术中产生的疑惑或实践问题,其他用户可通过在楼层下评论参与回答。 (回复格式参照本帖一楼) 参与规则:1. 同一ID不可自问自答;2. 同一ID可回复其他同一ID问题数量需≤3次,如,A最多可回答B的三个问题,但A可回答B、C、D、E、F等多人次问题。3. 每个人最多可发布20个有效问题,不可重复,不可灌水。4. 每个ID回答次数不设上限,但是否被采纳要依据专家评审后的结果。 活动奖励:由专家经过评审:◎每个有效提问可获得2积分。每周由专家评定,更新排行榜,上限为20个问题,不得灌水,不得与他人显示,问题具有意义,占楼无效。有效提问示例:无效提问示例:◎同一问题下确定一名最佳答案。提问者可获得5积分,被采纳的回答者可获得10积分。活动结束后,会根据排位赛积分情况,评选出前5名优秀答题官,由专家根据问题质量评选出5名优秀提问官,获取活动奖品华为云定制双肩包。2020年12月21日已由专家评审出5位优秀答题官和5名优秀提问官(1221直播选出)以下为中奖小伙伴华为云社区昵称,请看到自己昵称的小伙伴在12月31日前编辑“移动问答官+华为云账号+姓名+电话+地址”私信给7号版主(电脑版帖子左边版主头像下面发消息),过期不候哦~优秀答题官:@运气男孩@烟雨十年@考过IE励志当攻城狮@关关雎鸠在河之洲_@帅气的我优秀提问官:@谭涟漪@虚荣vainglory@初学者7000@蓝瘦的蜕变@HB1688恭喜以上10位小伙伴哦~你们将获得华为云定制高级双肩包,大家按要求回复地址信息哦~各阶段积分排行榜奖品三个阶段总积分排行榜奖品 活动注意事项1. 学习任务提交后,小助手会在本阶段学习周期内,按序完成审核,并增加活动积分;2. 请务必按照上述要求提交内容,以免影响积分增加;3. 若积分值相同则以完成学习任务的时间先后排序,其中任务完成时间的判定优先级为:阶段考核>问答官>分享转发>每周学习笔记>每章随堂测验;4. 其他积分获取方式请查看活动社群公告。想了解更多关于全栈成长计划课程内容请移步主帖:https://bbs.huaweicloud.com/forum/thread-84766-1-1.html除了本帖任务,其他学习任务可以通过以下链接进行查看:查看随堂测验打卡帖:https://bbs.huaweicloud.com/forum/thread-87346-1-1.html查看每周读书笔记打卡帖:https://bbs.huaweicloud.com/forum/thread-87350-1-1.html
-
简介帮助用户快速启动应用程序中的常见或推荐功能创建方式静态快捷方式:在打包到APK或应用包中的资源文件中定义。适合在用户与应用程序互动的整个生命周期内使用一致结构链接到内容的应用程序,即固定功能,固定跳转的页面。动态快捷方式:只能在运行时由应用发布,更新和删除(静态和动态加在一起最多四个,因为大多数启动器只能显示四个)。用于上下文相关的应用程序中的操作,快捷方式将需要经常更新。固定快捷方式:如果用户授予许可,则可以在运行时将固定的快捷方式添加到受支持的启动器中(无数量限制)。该方式生成的快捷方式内容一般由用户驱动,比如浏览器生成特定网页的快捷方式、遥控器生成特定设备的快捷方式。使用静态快捷方式在res下新建xml文件夹,然后新建文件作为静态快捷方式配置文件,这边新建的文件名叫shortcuts.xml,填写快捷方式相关配置<?xml version="1.0" encoding="utf-8"?><!--根标签是shortcuts代表一堆快捷方式--><shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> <!--每个shortcut标签代表一个快捷方式--> <shortcut <!--必须值:ID值,后面动态时可通过这个ID控制该快捷方式的显示或隐藏,不可以使用String资源文件里面的值引入--> android:shortcutId="play" <!--必须值:显示快捷方式后的简短描述,长度不超过10个字符--> android:shortcutShortLabel="@string/play_shortcut_short_label" <!--可选值:扩展短语,有足够空间才展示,长度不超过25个字符--> android:shortcutLongLabel="@string/play_shortcut_long_label" <!--可选值:默认true,如果设置为false,用户点击该快捷方式时无效,这时最好配置shortcutDisabledMessage告诉用户为什么无效--> android:enabled="true" <!--可选值:当该快捷方式无效时提示文字,enabled为true不起作用--> android:shortcutDisabledMessage="@string/play_disabled_message" <!--可选值:快捷方式的图标--> android:icon="@drawable/video"> <!--用户点击该快捷方式发生的意图--> <intent android:action="android.intent.action.VIEW" <!--注意:这边是应用包名,写错会无法打开指定页面--> android:targetPackage="com.dean.smartApp" android:targetClass="com.dean.smartApp.MainActivity"> <!--通过intent意图里面配置extra来告诉MainActivity需要展示的fragment--> <extra android:name="shortcut" android:value="play"/> </intent> <!--为应用程序的快捷方式执行的操作类型提供分组,例如创建新的聊天消息--> <categories android:name="android.shortcut.conversation" /> </shortcut> <shortcut android:shortcutId="music" android:enabled="true" android:icon="@drawable/music" android:shortcutShortLabel="@string/music_shortcut_short_label" android:shortcutLongLabel="@string/music_shortcut_long_label" android:shortcutDisabledMessage="@string/music_disabled_message"> <intent android:action="android.intent.action.VIEW" android:targetPackage="com.dean.smartApp" android:targetClass="com.dean.smartApp.MainActivity"> <extra android:name="shortcut" android:value="music"/> </intent> <categories android:name="android.shortcut.conversation" /> </shortcut></shortcuts>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354在Manifest启动Activity下添加配置文件<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" /> </activity>123456789动态快捷方式使用该方式可以引导用户自定义快捷方式以快速打开某个页面新建快捷方式,这边方法和上面xml中差不多ShortcutInfo shortcut = new ShortcutInfo.Builder(context, "play") .setShortLabel("高清影视") .setLongLabel("16K高清,不一样的体验") .setIcon(Icon.createWithResource(context, R.drawable.icon_shortcut_play)) .setIntent(playIntent) .build();123456更新快捷方式列表//通过SystemService获取Shortcut管理类ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);//通过setDynamicShortcuts替换原有整个快捷方式列表shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut));//也可以通过addDynamicShortcuts来增加一些快捷方式shortcutManager.addDynamicShortcuts(Arrays.asList(shortcut));//也可以通过updateShortcuts来更新原有的快捷方式列表shortcutManager.updateShortcuts(Arrays.asList(shortcut));//移除所有快捷方式shortcutManager.removeAllDynamicShortcuts();//通过ID删除指定的快捷方式shortcutManager.removeDynamicShortcuts(shortcutIds);123456789101112固定快捷方式Android 8.0(API级别26)及更高版本上支持第一种:之前静态和动态创建的快捷方式,在桌面长按应用图标会显示快捷方式列表,这时长按列表某一项然后拖动到桌面空白位置即可。第二种:代码创建//获取ShortcutManagerShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);//通过isRequestPinShortcutSupported来判断当前设备是否支持固定快捷方式if (shortcutManager.isRequestPinShortcutSupported()) { //拿到需要固定的快捷方式,可以是之前静态或动态创建好的 ShortcutInfo pinShortcutInfo = new ShortcutInfo.Builder(context, "play").build(); //创建一个意图 Intent pinnedShortcutCallbackIntent = shortcutManager.createShortcutResultIntent(pinShortcutInfo); //和其他系统控件交互一样需要延时意图PendingIntent PendingIntent successCallback = PendingIntent.getBroadcast(context,0,pinnedShortcutCallbackIntent,0); //创建固定快捷方式 shortcutManager.requestPinShortcut(pinShortcutInfo,successCallback.getIntentSender());}
-
区分外置U盘及TF卡最近有个项目有内置SD卡同时又保留了USB及sd卡口,由于要计算外置存储设备的空间,尝试了几个方法均不理想最终使用如下方法 可以成功的区分外置设备是U盘还是SD卡。主要通过如下方法区分U盘及TF卡 @SuppressLint("PrivateApi") private String getStoragePath(Context context, boolean isUsb){ String path=""; StorageManager mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); Class<?> volumeInfoClazz; Class<?> diskInfoClaszz; try { volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo"); diskInfoClaszz = Class.forName("android.os.storage.DiskInfo"); Method StorageManager_getVolumes=Class.forName("android.os.storage.StorageManager").getMethod("getVolumes"); Method VolumeInfo_GetDisk = volumeInfoClazz.getMethod("getDisk"); Method VolumeInfo_GetPath = volumeInfoClazz.getMethod("getPath"); Method DiskInfo_IsUsb = diskInfoClaszz.getMethod("isUsb"); Method DiskInfo_IsSd = diskInfoClaszz.getMethod("isSd"); List<Object> List_VolumeInfo = (List<Object>) StorageManager_getVolumes.invoke(mStorageManager); assert List_VolumeInfo != null; for(int i=0; i<List_VolumeInfo.size(); i++){ Object volumeInfo = List_VolumeInfo.get(i); Object diskInfo = VolumeInfo_GetDisk.invoke(volumeInfo); if(diskInfo==null)continue; boolean sd= (boolean) DiskInfo_IsSd.invoke(diskInfo); boolean usb= (boolean) DiskInfo_IsUsb.invoke(diskInfo); File file= (File) VolumeInfo_GetPath.invoke(volumeInfo); if(isUsb == usb){//usb assert file != null; path=file.getAbsolutePath(); }else if(!isUsb == sd){//sd assert file != null; path=file.getAbsolutePath(); } } } catch (Exception e) { YYLog.print(TAG, "[——————— ——————— Exception:"+e.getMessage()+"]"); e.printStackTrace(); } return path; }
-
原代码,this变红protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = findViewById(R.id.btn_1); btn.setOnClickListener(this); }1234567看了很多方法,可以这样写btn.setOnClickListenerprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = findViewById(R.id.btn_1); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //具体操作 } }); }123456789101112但在setOnClickListener中无法访问intent,于是有下面这种解决方法: private Context ctx = this; //直接用context变量定义this final static String TAG = "MAINACTIVITY"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = findViewById(R.id.btn_1); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(); intent.setClass(ctx,Main2Activity.class); ctx.startActivity(intent); } }); }12345678910111213141516171819
-
跪求大神帮忙解决!!!以下是我从华为为下载的编程关于 “展示了分段并发上传大对象的用法” 。但是当我们跑完代码, 在模拟的手机,它显示“Create a demo busket for demo Error message: The location contraint is incompatible for the region specific endpoint this request was sent to. Error code: IllegalLocationConstraintExceprtion Request ID: 000000175.... Host ID:wQQYK..."public class MainActivity extends androidx.appcompat.app.AppCompatActivity{ private static final String endPoint = "https://obs.cn-north-4.myhuaweicloud.com"; private static final String ak = "E5DVZAAK95..."; private static final String sk = "PluwDOGzcWcFXXYdlNjsnITWrB4Hud7..."; private static String bucketName = "chenzi"; private static String objectKey = "my-obs-object-key-demo"; private static ExecutorService executorService = Executors.newFixedThreadPool(5); private static List<PartEtag> partETags = Collections.synchronizedList(new ArrayList<PartEtag>()); private static ObsClient obsClient; private static StringBuffer sb = new StringBuffer(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout2); //Toast.makeText(this, "hUAWEItYR", Toast.LENGTH_LONG).show(); ObsConfiguration config = new ObsConfiguration(); config.setSocketTimeout(30000); config.setConnectionTimeout(10000); config.setEndPoint(endPoint); /* * Constructs a obs client instance with your account for accessing OBS */ obsClient = new ObsClient(ak, sk, config); final TextView tv = (TextView)findViewById(R.id.tv); tv.setText("Click to start test"); // Toast.makeText(this, "hUAWEItYR", Toast.LENGTH_LONG).show(); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { tv.setClickable(false); AsyncTask<Void, Void, String> task = new ConcurrentUploadPartTask(); task.execute(); } }); } private static class PartUploader implements Runnable { private File sampleFile; private long offset; private long partSize; private int partNumber; private String uploadId; public PartUploader(File sampleFile, long offset, long partSize, int partNumber, String uploadId) { this.sampleFile = sampleFile; this.offset = offset; this.partSize = partSize; this.partNumber = partNumber; this.uploadId = uploadId; } @Override public void run() { try { UploadPartRequest uploadPartRequest = new UploadPartRequest(); uploadPartRequest.setBucketName(bucketName); uploadPartRequest.setObjectKey(objectKey); uploadPartRequest.setUploadId(this.uploadId); uploadPartRequest.setFile(this.sampleFile); uploadPartRequest.setPartSize(this.partSize); uploadPartRequest.setOffset(this.offset); uploadPartRequest.setPartNumber(this.partNumber); UploadPartResult uploadPartResult = obsClient.uploadPart(uploadPartRequest); sb.append("Part#" + this.partNumber + " done\n\n"); partETags.add(new PartEtag(uploadPartResult.getEtag(), uploadPartResult.getPartNumber())); } catch (Exception e) { e.printStackTrace(); } } } class ConcurrentUploadPartTask extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) { try { /* * Create bucket */ sb.append("Create a new bucket for demo\n\n"); obsClient.createBucket(bucketName); /* * Claim a upload id firstly */ String uploadId = claimUploadId(); sb.append("Claiming a new upload id " + uploadId + "\n\n"); long partSize = 5 * 1024 * 1024l;// 5MB File sampleFile = createSampleFile(); long fileLength = sampleFile.length(); long partCount = fileLength % partSize == 0 ? fileLength / partSize : fileLength / partSize + 1; if (partCount > 10000) { throw new RuntimeException("Total parts count should not exceed 10000"); } else { sb.append("Total parts count " + partCount + "\n\n"); } /* * Upload multiparts to your bucket */ sb.append("Begin to upload multiparts to OBS from a file\n\n"); for (int i = 0; i < partCount; i++) { long offset = i * partSize; long currPartSize = (i + 1 == partCount) ? fileLength - offset : partSize; executorService.execute(new PartUploader(sampleFile, offset, currPartSize, i + 1, uploadId)); } /* * Waiting for all parts finished */ executorService.shutdown(); while (!executorService.isTerminated()) { try { executorService.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } /* * Verify whether all parts are finished */ if (partETags.size() != partCount) { throw new IllegalStateException("Upload multiparts fail due to some parts are not finished yet"); } else { sb.append("Succeed to complete multiparts into an object named " + objectKey + "\n\n"); } /* * View all parts uploaded recently */ listAllParts(uploadId); /* * Complete to upload multiparts */ completeMultipartUpload(uploadId); return sb.toString(); } catch (ObsException e) { sb.append("\n\n"); sb.append("Response Code:" + e.getResponseCode()) .append("\n\n") .append("Error Message:" + e.getErrorMessage()) .append("\n\n") .append("Error Code:" + e.getErrorCode()) .append("\n\n") .append("Request ID:" + e.getErrorRequestId()) .append("\n\n") .append("Host ID:" + e.getErrorHostId()); return sb.toString(); } catch (Exception e) { sb.append("\n\n"); sb.append(e.getMessage()); return sb.toString(); } finally { if (obsClient != null) { try { /* * Close obs client */ obsClient.close(); } catch (IOException e) { } } } } @Override protected void onPostExecute(String result) { TextView tv = (TextView)findViewById(R.id.tv); tv.setText(result); tv.setOnClickListener(null); tv.setMovementMethod(ScrollingMovementMethod.getInstance()); } private String claimUploadId() throws ObsException { InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectKey); InitiateMultipartUploadResult result = obsClient.initiateMultipartUpload(request); return result.getUploadId(); } private File createSampleFile() throws IOException { File file = File.createTempFile("obs-android-sdk-", ".txt"); file.deleteOnExit(); Writer writer = new OutputStreamWriter(new FileOutputStream(file)); for (int i = 0; i < 1000000; i++) { writer.write(UUID.randomUUID() + "\n\n"); writer.write(UUID.randomUUID() + "\n\n"); } writer.flush(); writer.close(); return file; } private void completeMultipartUpload(String uploadId) throws ObsException { // Make part numbers in ascending order Collections.sort(partETags, new Comparator<PartEtag>() { @Override public int compare(PartEtag o1, PartEtag o2) { return o1.getPartNumber() - o2.getPartNumber(); } }); sb.append("Completing to upload multiparts\n\n"); CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectKey, uploadId, partETags); obsClient.completeMultipartUpload(completeMultipartUploadRequest); } private void listAllParts(String uploadId) throws ObsException { sb.append("Listing all parts......"); ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, objectKey, uploadId); ListPartsResult partListing = obsClient.listParts(listPartsRequest); for (Multipart part : partListing.getMultipartList()) { sb.append("\tPart#" + part.getPartNumber() + ", ETag=" + part.getEtag()); } sb.append("\n"); } }
-
配置lazydesk详细操作步骤如下:1、在PC上新建一个”文本文档.txt”,写入以下内容并保存。#is hide the toolbar(0 not hide, 1 hide) LazyDesk=1 #is close the client system when the vm is shutdowm(1 is yes) ShutdownLinkage=0将“文本文档.txt”重新命名为“config.properties”,点击“是(Y)”确认更改。 得到如下配置文件: 2、在TCM上制作Android补丁。*选择文件:即之前在PC上创建的“config.properties”配置文件。 3、将补丁安装到TC上。 4、完成后需在TC上重启cloud client。
-
终于有时间鼓捣一下新鲜出炉的HarmonyOS了,有过安卓的开发基础,很容易上手~首先是下载开发环境,基本上是全自动,下载gradle的时候稍微有点慢,喝一杯咖啡的时间吧。然后遇到第一个障碍:默认下载的是5.x.x的版本,提示gradle代理失效,搜了下,解决方法是建议将gradle版本设置改到6.6.1重新下载,安装,安装的时候需要把旧版本的gradle文件从HarmonyOS删掉,否则不会自动安装,重启动开发软件后会自动安装gradle。安装完成后提示重启系统。https://developer.harmonyos.com/cn/docs/documentation/doc-guides/start-first-page-0000000000038014按照官网的提示开始第一个project,直接copy 粘贴,然后跑个模拟器,需要在华为的开发网站上实名认证下账号,有两种方式,1银行卡2身份证,银行卡快。不得不说,模拟器相当友好,速度快,运行流畅,也可能是因为之前跑android模拟的时间有点久了,软硬件环境已经不可同日而语。模拟器跑的时候要登录,这个地方最好集成到DevEco,个人觉得,同时再开个窗口,稍微有点别扭。先把模拟器跑起来,然后再run程序。非常容易上手,nice!下一步就是呼唤跑真机了。做点啥呢?
-
一、添加依赖在 Module 级别的 build.gradle 中进行如下配置 :dependencies { // 使用 Android X 的应用添加该依赖 implementation 'pub.devrel:easypermissions:3.0.0' // 使用 Android Support Library 支持库 , 添加该依赖 implementation 'pub.devrel:easypermissions:2.0.1'}1234567注意 使用不同的支持库 , 需要配置不同的 EasyPermissions 依赖库 ;使用 Android X : 需要添加 3.0.0 版本的依赖 ;使用 Android Support Library 支持库 : 需要添加 2.0.1 版本的依赖 ;二、在 AndroidManifest.xml 中配置权限一定不要忘记在 AndroidManifest.xml 中配置权限 , 否则无法使用 ;<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="kim.hsl.easypermissions"> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>123456789101112131415161718192021222324252627三、权限申请最简单用法只需要在需要权限的时候调用 EasyPermissions.requestPermissions 方法即可 ;如果用户拒绝后 , 再次点击即可 ;package kim.hsl.easypermissionsimport android.Manifestimport android.os.Bundleimport android.util.Logimport android.view.Viewimport androidx.appcompat.app.AppCompatActivityimport pub.devrel.easypermissions.EasyPermissionsclass MainActivitySimple : AppCompatActivity(){ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } fun onCLick(view : View){ EasyPermissions.requestPermissions( this, "权限申请原理对话框 : 描述申请权限的原理", 100, // 下面是要申请的权限 可变参数列表 Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS, Manifest.permission.WRITE_EXTERNAL_STORAGE ) }}1234567891011121314151617181920212223242526272829303132四、推荐使用的用法推荐使用的用法 :① 先判定是否有权限 : 调用 EasyPermissions.hasPermissions 判定是否有权限 ;如果有 : 直接执行相关逻辑 ;如果没有 : 调用 EasyPermissions.requestPermissions 执行申请权限相关逻辑 ;② 权限授权完毕 : 执行完毕后再次调用相同的方法 , 这里需要使用 @AfterPermissionGranted 注解 ;如果用户拒绝权限 , 就不让用户继续使用后续功能 , 不能处理永久拒绝的情况 ;package kim.hsl.easypermissionsimport android.Manifestimport android.os.Bundleimport android.view.Viewimport android.widget.Toastimport androidx.appcompat.app.AppCompatActivityimport pub.devrel.easypermissions.AfterPermissionGrantedimport pub.devrel.easypermissions.EasyPermissionsclass MainActivitySimple2 : AppCompatActivity(){ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } fun onCLick(view : View){ doSomethingWithPermissions() } @AfterPermissionGranted( 100 ) fun doSomethingWithPermissions(){ if(EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS, Manifest.permission.WRITE_EXTERNAL_STORAGE)){ // 如果有上述权限, 执行该操作 Toast.makeText(this, "权限申请通过", Toast.LENGTH_LONG).show() }else{ // 如果没有上述权限 , 那么申请权限 EasyPermissions.requestPermissions( this, "权限申请原理对话框 : 描述申请权限的原理", 100, Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS, Manifest.permission.WRITE_EXTERNAL_STORAGE ) } }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748五、GitHub 地址https://github.com/han1202012/EasyPermissions
上滑加载中
推荐直播
-
在昇腾云上部署使用DeepSeek
2025/02/14 周五 16:30-18:00
Hao-资深昇腾云解决方案专家
昇腾云上有多种方法部署DeepSeek,讲师一步步演示,解析配置参数的含义和推荐的选择。学完一起动手搭建自己的DeepSeek环境吧!
即将直播
热门标签