关于android:MobTech-秒验防控羊毛党

羊毛党利用各种伎俩,通过虚伪注册、登录、领券、下单等操作,套取平台的优惠、返利、积分等资源。他们通常应用设施牧场、模拟器等工具,批量生成大量的手机号码和设施信息,进行歹意刷单。这样不仅给平台造成微小的经济损失,也毁坏了失常用户的体验和信赖,影响了营销成果。 秒验是一种利用运营商的数据网关认证能力,实现手机号免密登录的技术。它能够在3秒内实现用户的注册或登录,比短信验证码快10倍,操作更平安、便捷、低时延。秒验有两种认证形式,一种是通过用户受权获取本机号码与网关进行比对认证,另一种是用户输出手机号码与网关进行验证是否为本机号码。 秒验如何防控羊毛党呢?次要有以下几个方面: 秒验能够精确辨认用户的手机号码和设施信息,与运营商数据网关进行电信级认证,防止了接码平台和模拟器等工具的烦扰,进步了认证的准确性和可靠性。秒验能够依据用户的手机号码和设施信息,进行危险评估和行为剖析,辨认出异样或可疑的用户,进行拦挡或提醒,升高了歹意刷单的可能性。秒验能够依据用户的手机号码和设施信息,进行标签打分和画像建模,精准定位指标用户群体,进行个性化举荐和优惠策略,进步了营销转化率和效率。秒验能够依据用户的手机号码和设施信息,进行数据统计和剖析,监测和评估营销流动的成果和收益,及时调整和优化营销计划和流程。

March 30, 2023 · 1 min · jiezi

关于android:MobTech-秒验本机号码一键登录

秒验是一种利用运营商的数据网关认证能力,实现手机号免密登录的技术。它能够在3秒内实现用户的注册或登录,比短信验证码快10倍,操作更平安、便捷、低时延。秒验有两种认证形式,一种是通过用户受权获取本机号码与网关进行比对认证,另一种是用户输出手机号码与网关进行验证是否为本机号码。 用户受权一键登录注册交互过程用户关上APP,点击一键登录按钮,弹出受权页面。用户点击批准受权,APP调用SDK发动网关认证申请,并获取accessCode。APP将accessCode和手机号发送给服务端,服务端调用API获取认证后果。如果认证后果为统一,服务端实现用户注册或登录,并返回胜利信息给APP;如果认证后果为不统一或无奈判断,服务端返回失败信息给APP,并疏导用户应用其余形式进行认证。用户输出手机号码进行比对认证交互过程用户关上APP,输出手机号码,点击获取验证码按钮。APP调用SDK发动网关认证申请,并获取accessCode。APP将accessCode和手机号发送给服务端,服务端调用API获取认证后果。如果认证后果为统一,服务端间接实现用户注册或登录,并返回胜利信息给APP;如果认证后果为不统一或无奈判断,服务端发送短信验证码给用户,并期待用户输出验证码进行验证。秒验的劣势秒验能够进步用户注册或登录的效率和体验,缩小用户的操作步骤和等待时间。秒验能够升高短信验证码的老本和危险,防止短信被拦挡、提早、滥用等问题。秒验能够进步用户的安全性和隐衷性,防止用户名和明码的泄露、撞库、拖库等问题。秒验能够反对三网手机号、虚构运营商号、携号转网号码,只需一次开发接入即可。秒验能够防控羊毛党利用接码平台、设施牧场等伎俩套取平台优惠,进步营销计划成果。秒验能够利用于以手机号进行注册、登陆、平安风控的场景,可实现用户无感知校验,拓宽校验场景。秒验的应用案例电商平台:秒验能够进步用户注册或登录的转化率,晋升用户体验和忠诚度,同时升高短信验证码的老本和危险。社交平台:秒验能够简化用户注册或登录的流程,减少用户的活跃度和留存率,同时爱护用户的隐衷和平安。金融平台:秒验能够晋升用户注册或登录的效率和体验,加强用户的信赖和满意度,同时进步用户的平安风控能力。游戏平台:秒验能够优化用户注册或登录的界面和交互,进步用户的参与度和付费率,同时避免用户的账号被盗和舞弊。

March 30, 2023 · 1 min · jiezi

关于android:ShareSDK-Android端权限说明

ShareSDK应用权限状况权限 权限阐明 是否必须 INTERNET 容许应用程序联网 必须 ACCESS\_NETWORK\_STATE 容许拜访网络状态 必须 READ\_PHONE\_STATE 读取设施标识 非必须 WRITE\_EXTERNAL\_STORAGE 用于缓存分享图片、log日志和设施标识,以及文件锁的应用 非必须 ACCESS\_FINE\_LOCATION 用于分享SDK治理后盾的区域分析性能展现 非必须 ACCESS\_COARSE\_LOCATION 用于分享SDK治理后盾的区域分析性能展现 非必须 QUERY\_ALL\_PACKAGES 用于高版本Android零碎手机中判断第三方平台是否装置 非必须(Android10以上的版本须要) 去除非必须的权限一般权限去除能够在module模块中的build.gradle文件中增加以下的配置去除Gradle主动加载的可选权限办法,去除之后无需增加其余配置性能能够失常应用: permissions { exclude "须要去除的权限1", "须要去除的权限2"}比方须要去除掉“android.permission.READ\_PHONE\_STATE”权限,则间接增加如下配置即可: MobSDK { appKey "Mob开发者后盾申请的AppKey" appSecret "Mob开发者后盾申请的AppSecret" ShareSDK { devInfo { ... } } permissions { exclude "android.permission.READ_PHONE_STATE" }}QUERY\_ALL\_PACKAGES权限去除阐明:Android高版本(Android10以上)判断第三方平台是否装置须要应用QUERY\_ALL\_PACKAGES权限,如果没有这个权限ShareSDK分享、受权无奈应用,不过因为Google商店对QUERY\_ALL\_PACKAGES权限审核比拟严格,如您不心愿应用QUERY\_ALL\_PACKAGES权限,能够应用咱们提供exclude的形式去除QUERY\_ALL\_PACKAGES权限: MobSDK { appKey "Mob开发者后盾申请的AppKey" appSecret "Mob开发者后盾申请的AppSecret" ShareSDK { devInfo { ... } } permissions { exclude "android.permission.QUERY_ALL_PACKAGES" }}须要留神的是去除QUERY\_ALL\_PACKAGES权限之后,须要在Manifest中通过"queries标签"手动配置一下须要应用的第三方平台包名,相似这样: <manifest package="xxxxxx"> ......<queries> <!--WhatsApp--> <package android:name="com.whatsapp" /> <!--Facebook--> <package android:name="com.facebook.katana" /> <!--Line客户端--> <package android:name="jp.naver.line.android" /> <!--Google包名--> <package android:name="com.google.android.gm"/> <package android:name="com.google.android.gms"/> <package android:name="com.google.android.apps.plus"/> <!--Twitter--> <package android:name="com.twitter.android" /> <!--WeChat--> <package android:name="com.tencent.mm" /> <!--QQ--> <package android:name="com.tencent.mobileqq" /> <!--instagram--> <package android:name="com.instagram.android" /> <!--FacebookMessenger--> <package android:name="com.facebook.orca" /> <!--新浪微博--> <package android:name="com.sina.weibo" /> ...... </queries>......</manifest>

March 30, 2023 · 1 min · jiezi

关于android:ShareSDK-Android-SDK-API

获取用户信息接口(showUser)//cn.sharesdk.framework/** * 获取用户信息 * @param account 获取指定账号的用户信息,间接设置成null */ public void showUser(String account)示例代码 //设置受权登录的平台Platform plat = ShareSDK.getPlatform(QQ.NAME);//受权回调监听,监听oncomplete,onerror,oncancel三种状态plat.setPlatformActionListener(platformActionListener);//抖音登录适配安卓9.0//ShareSDK.setActivity(MainActivity.this);plat.showUser(null);受权接口(authorize)//cn.sharesdk.framework/** * 第三方受权 */ public void authorize()示例代码 Platform plat = ShareSDK.getPlatform(Facebook.NAME);//受权回调监听,监听oncomplete,onerror,oncancel三种状态plat.setPlatformActionListener(new PlatformActionListener() { public void onError(Platform platform, int i, Throwable throwable) { //失败的回调,受权失败的回调 platform:平台对象,i:示意以后的动作(9示意分享),throwable:异样信息 } public void onComplete(Platform platform, int i, HashMap arg2) { //分享胜利的回调 } public void onCancel(Platform platform, int i) { //勾销分享的回调 }});//抖音登录适配安卓9.0//ShareSDK.setActivity(this);plat.authorize();其余辅助接口除此办法,ShareSDK还提供一些辅助办法,如下所示: plat.removeAccount(true) 移除受权状态和本地缓存,下次受权会从新受权获取新的受权信息 plat.SSOSetting(false) SSO受权,传false默认是客户端受权,没有客户端受权或者不反对客户端受权会跳web受权;设置成true是敞开SSO受权(敞开客户端受权) plat.setPlatformActionListener(this) 受权回调监听,监听oncomplete,onerror,oncancel三种状态 plat.isAuthValid() 判断是否曾经存在受权状态,能够依据本人的登录逻辑设置 ShareSDK.setActivity(this); ...

March 30, 2023 · 3 min · jiezi

关于android:MobTech-SMSSDK短信验证服务

短信验证服务能够帮忙开发者实现用户注册、登录、领取、平安校验等场景的短信验证性能。市面上常见的短信验证服务商有: MobTech:寰球当先的挪动开发者服务平台,提供SMSSDK,一款业余收费的短信验证码服务,反对寰球200多个国家和地区的手机号码验证。腾讯云:国内出名的云计算服务提供商,提供SMS,一款稳固牢靠,平安合规的短信触达服务,反对发送验证码、告诉类短信和营销短信。华兴软通:国内优质的短信服务商,提供10690短信平台,一款业余高效的短信群发平台,反对发送验证码、告诉类短信和营销短信。AutoFications:国外业余的短信接码平台,提供全自动短信验证服务,反对任何网站或应用程序的虚构电话号码。互亿无线:国内业余的106短信平台服务商,提供验证码短信接口、国内短信、语音告诉等产品,反对多种开发语言调用接入。MobTech与其余短信验证服务商相比,有以下几个劣势: 收费试用:MobTech为开发者提供收费的短信验证码额度,无需领取任何费用,满足非商用我的项目的需要。简略集成:MobTech提供了欠缺的开发文档和示例代码,开发者只须要几行代码就能够实现短信验证性能。寰球笼罩:MobTech反对寰球200多个国家和地区的手机号码验证,适应不同地区和网络环境的用户需要。数据安全:MobTech采纳高强度加密算法和平安通道,保障短信验证码的平安传输和存储,避免数据泄露和篡改。

March 29, 2023 · 1 min · jiezi

关于android:MobTech-MobPush用户行为分析

你是否想晓得你的用户都在什么时候关上你的利用?他们会不会因为你的推送而留下来?他们为什么会卸载你的利用?他们有没有关上告诉权限?这些问题都能够通过用户行为剖析来解答。用户行为剖析就是通过收集和剖析用户在利用中的行为数据,来揭示用户的特色、需要、偏好和问题,从而为推送服务提供数据反对和优化倡议。 用户行为剖析能够帮忙你: 理解用户群体的特点和差别,实现用户画像和分群,进步推送的精准度和个性化。把握用户的应用习惯和沉闷法则,抉择适合的推送机会和频率,进步推送的有效性和及时性。发现用户的问题和痛点,如卸载起因、权限敞开起因等,采取相应的措施和策略,进步推送的满意度和留存率。MobPush是一款业余收费的推送SDK,由MobTech提供,能够帮忙开发者实现智能化的推送服务。MobPush提供了弱小的用户行为剖析性能,基于Mob大数据平台,能够统计用户在利用中的各种行为数据,并在MobPush后盾展现清晰的数据报表。开发者只须要在利用中集成MobPush SDK,并在MobPush后盾查看相应的数据指标,就能够实现用户行为剖析。 MobPush后盾提供了以下几种用户行为剖析指标: 用户沉闷时段:统计不同时间段内的沉闷设施数,帮忙开发者抉择最佳的推送时段。用户留存率:统计不同时间段内的留存设施数和比例,帮忙开发者评估推送对用户留存的影响。用户卸载状况:统计不同渠道、包名、版本等维度下的卸载设施数和比例,帮忙开发者剖析卸载起因和趋势。告诉权限开关:统计不同渠道、包名、版本等维度下的告诉权限开启设施数和比例,帮忙开发者理解推送达到率受限因素。

March 29, 2023 · 1 min · jiezi

关于android:Java的线程和线程池的以及Executor线程框架理解

Java的线程和线程池的了解一:概念在Java中,应用线程来异步执行工作。Java的线程既是工作单元,也是执行机制。从JDK 5开始,把工作单元与执行机制拆散开来。工作单元包含Runnable和Callable,而执行机制由Executor框架提供。 二:什么是Executor框架?咱们晓得线程池就是线程的汇合,线程池集中管理线程,以实现线程的重用,升高资源耗费,进步响应速度等。线程用于执行异步工作,单个的线程既是工作单元也是执行机制,从JDK1.5开始,为了把工作单元与执行机制分来到,Executor框架诞生了,他是一个用于对立创立与运行的接口。Executor框架实现的就是线程池的性能 三:Executor的构造Executor框架次要由3大部分组成如下。1.工作:包含被执行工作须要实现的接口:Runnable接口或Callable接口。2.工作的执行:包含工作执行机制的外围接口Executor,以及继承自Executor的ExecutorService接口。Executor框架有两个要害类实现了ExecutorService接口(ThreadPoolExecutor和ScheduledThreadPoolExecutor)。3.异步计算的后果:包含接口Future和实现Future接口的FutureTask类。Executor框架蕴含的次要的类与接口如下图所示 四:对框架的了解Executor是一个接口,它是Executor框架的根底,它将工作的提交与工作的执行拆散开来 //我了解的这是一个定义线程一个行为,工作执行,具体交由其实现实现public interface Executor { void execute(Runnable command);}ExecutorService 也是一个接口 继承Executor接口 扩大Executor public interface ExecutorService extends Executor {//进行接管新工作,原来的工作继续执行 void shutdown();//进行接管新工作,原来的工作进行执行List<Runnable> shutdownNow();//接管的参数不一样 submit()能够承受runnable无返回值和callable有返回值execute()承受runnable 无返回值<T> Future<T> submit(Callable<T> task);}AbstractExecutorService 是一个抽象类 实现ExecutorService接口扩大性能ScheduledExecutorService(提早的线程池服务)是一个接口 继承ExecutorService接口扩大性能线程池外围类:ThreadPoolExecutor 继承AbstractExecutorService 的线程池类 public class ThreadPoolExecutor extends AbstractExecutorService {//构造方法//corePoolSize 外围线程 指定了线程池中的线程数量,它的数量决定了增加的工作是开拓新的线程去执行,还是放到workQueue工作队列中去;//maximumPoolSize 指定了线程池中的最大线程数量,这个参数会依据你应用的workQueue工作队列的类型,决定线程池会开拓的最大线程数量;//keepAliveTime 当线程池中闲暇线程数量超过corePoolSize时,多余的线程会在多长时间内被销毁;(闲暇线程包活工夫)//unit:keepAliveTime的单位//workQueue:工作队列,被增加到线程池中,但尚未被执行的工作;它个别分为间接提交队列、有界工作队列、无界工作队列、优先工作队列几种;(阻塞队列长度设置为Integer.MAX_VALUE)//threadFactory:线程工厂,用于创立线程,个别用默认即可;//handler:回绝策略;当工作太多来不及解决时,如何回绝工作; public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); }}//例如线程池外围线程数为1,最大线程数为10,工作队列容量(阻塞队列)queueCapacity也就是BlockingQueue工作10个默认线程池的数量为1,当工作不超过10个,会在工作队列排队期待线程池里一个线程解决当工作>10个,会创立一个新的线程解决当线程数达到最大线程数的时候 RejectedExecutionHandler(工作回绝处理器) 回绝策略RejectedExecutionHandler(回绝策略) 接口有上面几个实现类 如果没有设置,默认是AbortPolicy,会抛出异样。 ...

March 29, 2023 · 2 min · jiezi

关于android:运动健康路线导入助力用户轻松导航

华为HMS Core静止衰弱服务反对通过REST API,以GPX文件格式写入用户路线数据,反对导入轨迹(Track)或途程(Route)类型的数据,实现用户路线数据在华为静止衰弱App中的展现成果。 假若与华为静止衰弱App相连接的穿戴设施反对路线导入,那么用户路线数据将主动下发至穿戴设施。用户可应用手表轻松导航,依照既定路线进行跑步、爬山等流动。(以后反对的设施有:HUAWEI WATCH GT 3系列、HUAWEI WATCH GT RUNNER。您能够在华为静止衰弱App—我的—我的线路中查看最新的路线导入设施反对状况。) 流程如下:用户通过生态利用导出GPX文件。 生态利用通过调用REST API实现路线数据写入,并通过响应体获取路线ID(routeId)。 依据上一步返回的路线ID,通过DeepLink形式实现路线主动导入至华为静止衰弱App。 路线导入对应的Scope权限为:https://www.huawei.com/healthkit/location.write 路线数据写入场景化示例代码Route路线写入申请示例PUThttps://health-api.cloud.huawei.com/healthkit/v1/routeInfos?format=GPX申请体Content-Type: application/xmlAuthorization: Bearer ***x-client-id: ***x-version: ***x-caller-trace-id: ***<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><gpx version="1.1" creator="***" xmlns:xsi="***" xmlns="***" xsi:schemaLocation="***"> <metadata> <time>1970-01-01T00:00:00Z</time> </metadata> <extensions> <totalTime>10000</totalTime> <totalDistance>10000</totalDistance> <routeName>testRouteName</routeName> </extensions> <rte> <rtept lat="24.27207756704355" lon="98.6666815648492"> <ele>2186.0</ele> </rtept> <rtept lat="24.27218810046418" lon="98.66668171910422"> <ele>2188.0</ele> </rtept> <rtept lat="24.27229019048912" lon="98.6667668786458"> <ele>2188.0</ele> </rtept> <rtept lat="24.27242784195029" lon="98.6668908573738"> <ele>2188.0</ele> </rtept></rte></gpx>响应体HTTP/1.1 200 OKContent-type: application/json;charset=utf-8{ "routeId": 167001079583340846}Track路线导入申请示例PUThttps://health-api.cloud.huawei.com/healthkit/v1/routeInfos?format=GPX申请体Content-Type: application/xmlAuthorization: Bearer ***x-client-id: ***x-version: ***x-caller-trace-id: ***<?xml version="1.0" encoding="UTF-8"?><gpx creator="***" version="1.1" xsi:schemaLocation="***" xmlns:ns3="***" xmlns="***" xmlns:xsi="***" xmlns:ns2="***"> <metadata> <time>2021-06-30T10:34:55.000Z</time> </metadata> <extensions> <totalTime>10000</totalTime> <totalDistance>10000</totalDistance> <routeName>testRouteName2</routeName> </extensions> <trk> <name>跑步</name> <type>running</type> <trkseg> <trkpt lat="22.6551113091409206390380859375" lon="114.05494303442537784576416015625"> <ele>-33.200000762939453125</ele> <time>2021-06-30T10:35:09.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>31.0</ns3:atemp> <ns3:hr>110</ns3:hr> <ns3:cad>79</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> <trkpt lat="22.655114494264125823974609375" lon="114.05494051985442638397216796875"> <ele>-33.40000152587890625</ele> <time>2021-06-30T10:35:10.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>31.0</ns3:atemp> <ns3:hr>111</ns3:hr> <ns3:cad>79</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> <trkpt lat="22.65512078069150447845458984375" lon="114.05494404025375843048095703125"> <ele>-33.59999847412109375</ele> <time>2021-06-30T10:35:11.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>31.0</ns3:atemp> <ns3:hr>112</ns3:hr> <ns3:cad>79</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> <trkpt lat="22.654982395470142364501953125" lon="114.05491151846945285797119140625"> <ele>-33.59999847412109375</ele> <time>2021-06-30T10:35:13.000Z</time> <extensions> <ns3:TrackPointExtension> <ns3:atemp>31.0</ns3:atemp> <ns3:hr>114</ns3:hr> <ns3:cad>77</ns3:cad> </ns3:TrackPointExtension> </extensions> </trkpt> </trkseg> </trk></gpx>响应体HTTP/1.1 200 OKContent-type: application/json;charset=utf-8{ "routeId": 167001079583340846}DeepLink跳转静止衰弱App实现路线主动导入三方生态利用执行路线写入实现后,Health Kit服务端会生成并返回路线的惟一ID,生态利用可携带路线ID通过DeepLink形式跳转静止衰弱App我的路线详情页面,主动导入路线至静止衰弱App中。 ...

March 29, 2023 · 1 min · jiezi

关于android:MobTech-MobPush厂商通道支持

什么是厂商通道?厂商通道是指手机厂商提供的推送服务,如华为、小米、魅族、OPPO、vivo等。厂商通道能够利用手机零碎的个性,实现更稳固和高效的音讯推送,进步推送达到率和及时性。 为什么须要厂商通道?因为Android零碎的碎片化和多样化,不同的手机品牌和型号可能有不同的系统优化策略,如省电模式、后盾治理、自启动治理等。这些策略可能会影响第三方利用的推送服务,导致推送音讯无奈及时达到用户或者被拦挡。因而,须要借助厂商通道来解决这些问题,进步推送成果。 MobPush如何反对厂商通道?MobPush是一款业余收费的推送SDK,由MobTech提供,能够帮忙开发者实现智能化的推送服务。MobPush反对多种厂商通道,包含华为、小米、魅族、OPPO、vivo等。开发者只须要在MobPush后盾配置相应的厂商信息,并在利用中集成MobPush SDK,就能够实现厂商通道的接入和应用。 厂商通道有什么劣势?厂商通道有以下几个劣势: 进步推送达到率。厂商通道能够绕过零碎的限度和烦扰,间接将音讯发送到用户手机上,进步推送达到率和及时性。升高资源耗费。厂商通道能够缩小利用在后盾运行的工夫和频率,升高利用对手机电量和流量的耗费。丰盛推送款式。厂商通道能够反对更多品种和款式的推送音讯,如角标、大图、大文本、自定义铃声等,减少用户的注意力和趣味。兼容寰球推送。厂商通道能够反对国内外音讯触达,适应不同地区和网络环境的用户需要。总结厂商通道是指手机厂商提供的推送服务,能够利用手机零碎的个性,实现更稳固和高效的音讯推送,进步推送达到率和及时性。MobPush反对多种厂商通道,包含华为、小米、魅族、OPPO、vivo等。开发者只须要在MobPush后盾配置相应的厂商信息,并在利用中集成MobPush SDK,就能够实现厂商通道的接入和应用。厂商通道有助于进步推送达到率,升高资源耗费,丰盛推送款式,兼容寰球推送。

March 29, 2023 · 1 min · jiezi

关于android:MobTech-MobPush智能标签推送

智能标签推送是MobPush提供的一项高级性能,能够帮忙开发者实现千人千面的精准推送。智能标签推送的原理是,依据用户的行为、属性、偏好等数据,给用户打上不同的标签,而后依据标签来筛选指标用户群体,发送个性化的推送音讯。 智能标签推送有以下几个劣势: 进步用户活跃度和留存率。通过智能标签推送,能够依据用户的趣味、需要、习惯等,发送适合的内容和机会的音讯,进步用户的点击率和参与度,减少用户对利用的粘性和忠诚度。晋升经营效率和成果。通过智能标签推送,能够缩小人工设置和治理推送工作的工夫和老本,实现自动化和智能化的推送经营。同时,能够通过数据分析和A/B测试,优化推送策略和素材,晋升推送成果。加强用户体验和满意度。通过智能标签推送,能够防止给用户发送无关或反复的音讯,缩小用户的烦扰和恶感。同时,能够给用户发送更贴合其共性和爱好的音讯,减少用户的满意度和信赖。应用智能标签推送须要以下几个步骤: 集成MobPush SDK。开发者须要在利用中集成MobPush SDK,并在MobPush后盾创立利用并获取AppKey。设置用户标签。开发者能够通过MobPush SDK或API接口,给每个用户设置最多100个标签。标签能够是自定义的或者是MobPush提供的基于大数据分析的智能标签。创立推送工作。开发者能够在MobPush后盾或API接口,创立推送工作,并抉择指标人群为设置了某些标签的用户。同时,能够设置推送内容、款式、工夫、频率等参数。查看推送数据。开发者能够在MobPush后盾或API接口,查看每条推送工作的全链路数据统计分析,包含发送量、达到量、展现量、点击量等指标。同时,能够通过A/B测试,比拟不同素材或策略的推送成果。

March 29, 2023 · 1 min · jiezi

关于android:秒验-手机号码置换接口

性能阐明提交客户端获取到的token、opToken等数据,验证后返回手机号码调用地址POST http://identify.verify.mob.com/auth/auth/sdkClientFreeLogin申请头Content-Type :application/json入参阐明字段 类型 阐明 必传 appkey String app标识 Y token String 客户端的token Y opToken String 客户端返回的运营商token Y operator String 客户端返回的运营商,CMCC:中国移动通信, CUCC:中国联通通信, CTCC:中国电信 Y sign String 签名(MD5(所有参数应用key的正序,通过a=b&b=c+appSecret组成)) Y timestamp long 以后工夫戳(毫秒) Y md5 String APK的md5签名,例:e4caa1a08ba0570b5c1290b1a0bc9252 N 加密示例参数 "appkey" -> "2f2d7j9wf8a40""opToken" -> "f630dwff2f8f209c60a6449cf971ad50b3e83f4620a1536252457229836325""operator" -> "CUCC""token" -> "0:AAAAhAAAAIAIFOEDCVObiS1Pdyogg4JQw5Su4ce9rl/QVDaqKlcGDCzBssmrB3dYL3HcnNG9Gj7IzhiB/cRJF221cELTGHRiFGAjpGpjipkw/EbnoFuxjp3TPAhvprf/vqWm9dmUQCJ7P/+twKy5o5Y9XBBpD+W/jVPX/WbIQofYg3YGwAAAPDTY7g1X3rL326Dnlsifj/UDjoZ0Ftdh8qWG+ofn0P41bbO6q88id06vkU2x2eUEOb1RggqYt+BLHyG3PoLIC0AMGoUcTVyCcGYq15j+ZS23qiA2SLRYgwvvhD3N+HKTSWEPmYQDUKls5fckyQGW6x6yGB71NDUqwntBdQxwmT6W5NG379KyvPwRkZSN4cyJ29HugMMTx/0F9nF6YVgEogEHOms515lQ7f3TJqTidsVdIehQcDb2FdXnCJUjnOJTK4RWRHp9IvTxwXgmsT7WzkwWuSe/12sEx8Zdk2U66//nqgJ5c1FDbuHsqGlKA8fYyo=""timestamp" -> 1655190952281"appSecret" -> "9abee316611wd9ff607feb9f2c496338" 排序后果 appkey=2f2d7j9wf8a40&opToken=f630dwff2f8f209c60a6449cf971ad50b3e83f4620a1536252457229836325&operator=CUCC&timestamp=1655190952281&token=0:AAAAhAAAAIAIFOEDCVObiS1Pdyogg4JQw5Su4ce9rl/QVDaqKlcGDCzBssmrB3dYL3HcnNG9Gj7IzhiB/cRJF221cELTGHRiFGAjpGpjipkw/EbnoFuxjp3TPAhvprf/vqWm9dmUQCJ7P/+twKy5o5Y9XBBpD+W/jVPX/WbIQofYg3YGwAAAPDTY7g1X3rL326Dnlsifj/UDjoZ0Ftdh8qWG+ofn0P41bbO6q88id06vkU2x2eUEOb1RggqYt+BLHyG3PoLIC0AMGoUcTVyCcGYq15j+ZS23qiA2SLRYgwvvhD3N+HKTSWEPmYQDUKls5fckyQGW6x6yGB71NDUqwntBdQxwmT6W5NG379KyvPwRkZSN4cyJ29HugMMTx/0F9nF6YVgEogEHOms515lQ7f3TJqTidsVdIehQcDb2FdXnCJUjnOJTK4RWRHp9IvTxwXgmsT7WzkwWuSe/12sEx8Zdk2U66//nqgJ5c1FDbuHsqGlKA8fYyo= 计算结果 sign -> 3f1991b27b1c86a32e661eabdd3d1f5a 申请示例curl --location --request POST 'http://identify.verify.mob.com/auth/auth/sdkClientFreeLogin' \--header 'Content-Type: application/json' \--data-raw '{"token":"0:AAAAhAAAAIAIJn3PvTUUJ94umGqPmZCFtprF5Pg7uCxb+Opp+JtZrHIX3yxVOGEHJQLHuRLU1hlTbYyxCMfW53fuck6OL1X+01qdf+NpTVj1ApmQzapKWFB3DEPNNdyad8HwxZY/ZGWcch0Njy+Pb0TgqMwAytBWKu5vlvN9LRoWw/6F3K4BGgAAAPDHlbG1uFKewi7J1g3d6tAor/kIHG0A8csscrESYVfmVYzB6RBfQWfwDpZIYLrXOuSFdWP3bqKbEyIiqvSeY3ktxSus2lUdD6MzwYo1aXJ6oALEW/A07Qx5/3S6ClSmtGrHuzDnC6JCsmHEQWR7S2wNLSojS95Zd91AC2gpqV5tmKEaVGDc827JVEHXFX6Zr5d0pNmBHLS0b67BrNfG4v0qSgcf/OL3a1xOQVieqUDbrAPiNF7Q2wifCbj0FQyIt5+LPpOkqKDbYff21WinJMTOuOMoJcqOhrI1gUEmnHE/ZU8ZZXN52Kffd+Pk7aR7MMU=","opToken":"a53c2dc92083cb1375218a0f1dd35e0050bb26e40ba0a1536204920384995379", "appkey": "2f2d7a68f8a40", "operator": "CUCC", "sign": "576ec00ac6ad80a2d0a92872d748e82b", "timestamp": 1655094782181}'响应示例申请胜利 ...

March 29, 2023 · 3 min · jiezi

关于android:MobTech什么是SDK

SDK全称Software Development Kit,即软件开发工具包。个别都是一些软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建设应用程序时所应用的开发工具的汇合。 简略说就是第三方服务商或集体提供的实现软件产品某项性能的工具包。SDK通常应该蕴含一系列API供应用方调用,一份应用文档供应用方参考,它同时也能够蕴含以下内容: 编译器调试器运行时/开发环境测试/剖析工具应用sdk有以下几个方面的劣势: 省时省力:应用sdk能够防止反复造轮子,间接调用第三方提供的性能,节俭开发工夫和老本稳固牢靠:应用sdk能够保障性能的稳定性和可靠性,缩小出错和解体的危险平安高效:应用sdk能够保证数据的安全性和效率,无需与服务端进行数据交互,缩小流量耗费和提早多样灵便:应用sdk能够反对多种形式和场景的性能实现,适应不同的需要和平台sdk能够利用于各种畛域和场景,比方: 人脸识别:应用sdk能够实现人脸检测、人脸比对、人脸搜寻等性能,利用于安防、金融、教育等行业音讯推送:应用sdk能够实现多种推送模式和场景,实现精准用户触达和激活,利用于电商、社交、媒体等行业社会化登录分享:应用sdk能够实现40+支流平台的分享与受权等社会化性能,成果稳固,残缺清晰统计分享数据,利用于游戏、视频、音乐等行业短信验证:应用sdk能够实现短信与语音验证性能,反对国内外200+国家和地区的短信发送和接管,安全可靠,价格优惠,利用于注册、登录、领取等场景mobtech是寰球当先的挪动开发者服务平台,可满足挪动利用开发中SDK需要,涵盖深度链接、第三方登录分享、短信验证、音讯推送等性能。已累计帮忙近30万个开发者团队升高开发成本,进步集成效率,构建最贴心的一站式服务平台。 mobtech目前提供了以下六款SDK产品: MobPush:智能化推送服务,反对多种推送模式和场景,实现精准用户触达和激活ShareSDK:社会化登录分享组件,反对40+支流平台的分享与受权等社会化性能,成果稳固,残缺清晰统计分享数据秒验:运营商网关取号,一秒验证手机号,无需短信验证码,进步用户注册和登录效率短信验证:短信与语音验证性能,反对国内外200+国家和地区的短信发送和接管,安全可靠,价格优惠MobLink:挪动场景还原解决方案,实现Web与App之间的无缝链接,让用户从任何渠道进入App时,都能中转指定页面,无需从新注册或登录利用内广告:为开发者提供业余的广告变现解决方案,反对多种广告模式和平台,实现高效匹配和展现

March 28, 2023 · 1 min · jiezi

关于android:MobTech场景唤醒的实现

什么是场景唤醒?场景唤醒是moblink的一项外围性能,能够实现从关上的Web页面,一键唤醒App,并复原对应的场景。 场景是指用户在App内的某个特定页面或状态,比方商品详情页、流动页、个人主页等。每个场景都有一个惟一的标识符,能够通过moblink的SDK生成一个对应的短链或二维码。用户通过点击短链或扫描二维码,就能够进入App并复原该场景。 如果用户曾经装置了App,那么场景唤醒就是间接关上App并跳转到对应的页面。如果用户还没有装置App,那么场景唤醒就是先疏导用户下载并装置App,而后在首次启动时主动跳转到对应的页面。无论哪种状况,用户都无需从新注册或登录,也无需填写邀请码或其余信息。 为什么须要应用场景唤醒?应用场景唤醒能够带来以下几个方面的益处: 晋升用户体验:用户从任何渠道进入App时,都能中转指定页面,无需从新注册或登录,缩小用户操作步骤和等待时间,进步用户满意度和留存率减少用户转化:用户从Web页面一键唤醒App,并复原对应场景,减少用户对App的趣味和信任度,进步用户的装置率和注册率升高企业老本:开发人员无需开发、保护关系匹配零碎和短链生成零碎,节俭开发成本和运维老本;同时,应用moblink能够收费获取业余短链服务和数据统计服务反对多种场景:moblink反对多种形式的跳转形式和参数传递形式,能够实用于各种场景,如邀请好友、分享内容、流动推广、内容散发等如何应用场景唤醒?应用场景唤醒非常简单,只需以下几个步骤: 注册MobTech开发者账号:https://www.mob.com/mobService/moblink创立利用并抉择接入产品:抉择moblink产品,并填写利用信息SDK集成:查阅文档,并依据平台抉择对应的SDK进行集成场景配置:在后盾配置须要唤醒的场景,并生成对应的短链或二维码功能测试:测试场景唤醒性能是否失常运行正式应用:公布利用并享受场景唤醒带来的便当

March 28, 2023 · 1 min · jiezi

关于android:MobTech如何使用秒验

什么是秒验?秒验是MobTech公司提供的一款实现一键验证性能的产品,从本源上升高企业验证老本,无效进步拉新转化率,升高因验证带来的流失率,3秒实现手机号验证(一键登录)。 秒验次要整合了三大运营商独有的数据网关验证能力,实质上晋升了短信验证码的用户体验,可能用于用户注册、登陆、领取、平安校验等场景,可实现用户无感知校验,具备操作平安、便捷、低时延等特点。 如何应用秒验?应用秒验非常简单,只需以下几个步骤: 注册MobTech开发者账号:https://www.mob.com/mobService/secverify创立利用并抉择接入产品:抉择秒验产品,并填写利用信息SDK集成:查阅文档,并依据平台抉择对应的SDK进行集成功能测试:测试秒验性能是否失常运行正式应用:公布利用并享受秒验带来的便当上面咱们具体介绍一下每个步骤的操作方法。 注册MobTech开发者账号首先,你须要注册一个MobTech开发者账号,能力应用秒验等产品。你能够点击这里进入秒验官网,而后点击右上角的“注册”按钮,填写你的邮箱、明码、验证码等信息,批准服务条款和隐衷政策,而后点击“注册”按钮实现注册。 注册胜利后,你会收到一封激活邮件,你须要点击邮件中的链接激活你的账号。激活胜利后,你就能够登录你的MobTech开发者账号了。 创立利用并抉择接入产品登录后,你会进入MobTech开发者平台的工作台页面。这里你能够看到你曾经创立或接入的利用列表。如果你还没有创立或接入任何利用,你能够点击“创立利用”按钮开始创立一个新的利用。 在创立利用页面,你须要填写你的利用名称、利用类型(Android或iOS)、利用包名(Android)或Bundle ID(iOS)、利用图标等信息。而后点击“下一步”按钮。 在下一步页面,你能够抉择你想要接入的产品。这里咱们抉择“秒验”,而后点击“实现”按钮。 创立胜利后,你会看到你的利用信息页面。这里你能够看到你的AppKey和AppSecret等重要信息。请妥善保存这些信息,不要泄露给别人。这些信息将在SDK集成时应用。 SDK集成在实现利用创立和产品抉择后,你就能够开始SDK集成了。SDK集成分为Android和iOS两种平台。咱们别离介绍。 Android SDK集成Android SDK集成次要分为以下几个步骤: 下载SDK:你能够在这里下载秒验Android SDK,或者在你的利用信息页面点击“SDK下载”按钮下载。导入SDK:你能够将下载的SDK解压后,将其中的secverify-release.aar文件复制到你的我的项目的libs目录下。配置权限和元数据。初始化SDK。调用秒验性能。iOS SDK集成iOS SDK集成次要分为以下几个步骤: 下载SDK:你能够在这里下载秒验iOS SDK,或者在你的利用信息页面点击“SDK下载”按钮下载。导入SDK:你能够将下载的SDK解压后,将其中的SecVerify.framework文件拖拽到你的我的项目中,并勾选“Copy items if needed”选项。而后在你的我的项目的General页面,点击“Frameworks, Libraries, and Embedded Content”下的“+”按钮,增加SystemConfiguration.framework、CoreTelephony.framework、AdSupport.framework、libz.tbd、libsqlite3.tbd等依赖库。配置权限和元数据。初始化SDK。调用秒验性能。功能测试在实现SDK集成后,你能够进行功能测试,查看秒验性能是否失常运行。你能够应用真机或模拟器进行测试,然而请留神以下几点: 真机测试时,请确保手机插入SIM卡,并且开启挪动数据网络。模拟器测试时,请确保模拟器设置了正确的运营商信息,并且应用Wi-Fi网络。测试时,请应用不同的运营商号码进行测试,以查看三网的兼容性。测试时,请留神查看控制台的日志输入,以便发现和排查问题。正式应用在实现功能测试后,你就能够正式应用秒验性能了。你能够公布你的利用到各个利用市场,并享受秒验带来的便当。同时,你也能够登录MobTech开发者平台,查看你的利用的秒验数据统计和剖析,以及进行一些高级设置和治理。

March 28, 2023 · 1 min · jiezi

关于android:MobTech移动应用开发中的消息推送

音讯推送是挪动利用开发中不可或缺的一个性能,它能够实现以下几个目标: 拉活:通过产品各种个性(流动)吸引用户点击应用,进一步验证产品思路、方向;促成用户粘性:好比明天收到告诉,谁谁谁直播 ing,快马加鞭的点击进去开始膜拜;重大事件告诉与防备:科技的力量,在某些方面,总会统一战线,无时无刻提醒危险以及增强警觉;音讯推送最终的目标,集体更大的感觉还是将用户进一步留存,无论采取任何形式办法。 然而,Android平台上的音讯推送并不是一件容易的事件。因为Android的开放性使其本身逐渐发展壮大,同时开放性也衍生了国内各种厂商的定制化。各种 “零碎” 层出不穷,百花齐放的场景也给 Android 开发小伙伴带来了很多兼容性的问题。 那么对于咱们原生 Android 开发而言,如何解决,能达到最好的推送成果?我想那可能是顺次对支流厂商进行兼容适配,然而同时也带来了成倍的接入工作。 较好的一点是,有艰难,便有业余解决困难提供商。对于小公司而言,一键接入成型并且通过市场测验的三方推送服务便是上上策。 目前国内的推送服务商有很多,比拟出名的有极光、个推、友盟、百度等。那么,MobPush与它们有什么不同呢?咱们从以下几个方面进行简略的比照: 反对的音讯格局:MobPush反对告诉栏告诉、自定义音讯(透传)、本地告诉三种音讯格局,而极光还反对富媒体,友盟还反对Flutter,个推还反对分组比照等。离线厂商通道反对:MobPush反对华为、小米、魅族、OPPO、vivo五种厂商通道,而极光还反对华硕、FCM,个推还反对坚果、海信、索尼等。别名、标签反对:MobPush和其余三家都反对别名和标签的设置和治理,能够实现用户分群和精准推送。移除关联启动:MobPush和其余三家都不反对移除关联启动,即当用户点击告诉栏音讯时,会启动利用的主界面,而不是指定的界面。音讯撤回:MobPush和其余三家都反对音讯撤回,即当用户没有点击告诉栏音讯时,能够在后盾勾销该音讯的展现。卸载统计:MobPush和其余三家都反对卸载统计,即能够统计用户卸载利用的数量和起因。反对的平台:MobPush和极光都反对Android、iOS、Flutter、Unity、JavaScript、Cocos2d-X等多种平台,而个推只反对Android和iOS,友盟只反对Android和iOS。从下面的比照能够看出,MobPush在性能上与其余推送服务商相差不大,甚至在某些方面有劣势。那么,MobPush有什么特别之处呢? 除了根本的推送性能外,MobPush还有一些特色性能,让它更加突出: 全免费:MobPush是目前惟一一款全免费的推送服务商,无论是离线推送还是在线推送,无论是发送量级还是数据分析,都不收取任何费用。这对于中小型企业来说是十分有吸引力的。724小时业余技术支持:MobPush有业余的技术团队提供724小时的技术支持,无论是接入过程中遇到的问题还是经营过程中遇到的问题,都能够及时失去解决。这对于没有业余运维人员的企业来说是十分有帮忙的。智能路由:MobPush具备智能路由的特有性能,即用户抉择智能路由后,无需关怀 Push 发送时应用的厂商通道,易观方舟智能经营组件依据用户以后机型主动进行判断,抉择对应的厂商通道进行发送,保障极高达到率。MobPush是一款业余收费的音讯推送SDK,智能化推送服务。它能够帮忙开发者疾速集成实现推送性能,晋升用户活跃度,无效唤醒沉睡用户。它反对多种推送音讯类型,全链路数据统计分析,厂商通道集成,别名和标签治理等性能。它在性能上与其余推送服务商相差不大,甚至在某些方面有劣势。它还有一些特色性能,如全免费、7*24小时业余技术支持、智能路由、数据闭环等,让它更加突出。 如果你想要为你的利用减少音讯推送性能,或者想要优化你的音讯推送成果,无妨试试MobPush,它可能会给你带来意想不到的播种。

March 28, 2023 · 1 min · jiezi

关于android:ShareSDK常见问题

QQ-分享报错901111,9001010等因为QQ当初须要审核后才能够分享(之前分享不须要审核),所以此谬误解决办法只需通过腾讯开放平台的审核即可,另外要查看注册好的利用的根本信息,包名、md5签名和Bundle id是不是填写正确,和我的项目里是统一的; 开放平台申请流程各个开放平台,第三方平台,用ShareSDK分享也是须要申请,失去第三方的受权的,所以申请是必须的,申请流程您能够参考:链接 Facebook如何分享链接卡片的模式fb分享链接,是依据链接中的配置,主动获取的,无奈从客户端中设置代码或者接口来配置,只能通过前端的配置来操作,具体能够参考此处阐明:Facebook显示卡片成果 Android端微信分享多图微信分享多图会报如下谬误; 微信从6.7.3开始限度了多图的分享,从微信6.7.3版本之后微信的朋友圈还是好友都无奈分享多图的解决; Android端微信一个key是否能够绑定多个包名微信开放平台申请利用,一个key只能绑定一个包名,无奈绑定多个包名,如果须要申请多渠道包名的key的话,须要申请多个key; Android端微信没有回调微信回调:这个WXEntryActivity.java 类 必须要在wxapi下,wxapi必须要在您的工程的包名package下。此处的包名必须与您的微信开放平台配置的包名统一才能够的;目前ShareSDK提供了Gradle集成形式,会主动依据您的包名生成回调配置,如果gradle集成的话能够不须要本人手动配置; Android端ShareSDK跳到微信后,返回操作,勾销分享,还是提醒胜利您好,微信从6.7.2的版本之后批改了策略,是微信本人管制的,目前所有应用微信分享的都是这种成果; Android端ShareSDK for 微信小程序ShareSDK能够关上小程序吗? 能够的; ShareSDK能够分享后小程序,从小程序还原回app吗? 能够的,且能够本人携带参数,具体详情见链接:链接 Android端微信回调与利用宝渠道回调抵触微信规定回调类只能用WXEntryActivity。所以ShareSDK对其做了适配,如果利用宝抵触的话能够这样解决:链接 Android端新浪微博客户端分享报签名谬误查看没有微博状态是不是在草稿箱中,并且有SSO的相干提醒,此类问题个别是是因为微博开放平台配置的包名和签名与您的app的不统一导致的,确保签名和包名配置的 统一即可; Android端腾讯QQ与QZone分享没有回调,或者提醒勾销离线集成的话,须要在AndroidManifest中配置QQ的回调配置; <activity android:name="cn.sharesdk.tencent.qq.ReceiveActivity" android:launchMode="2" android:noHistory="true"> <intent-filter> <data android:scheme="tencent100371282" /> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> </intent-filter></activity>其中,tencent前面的是QQ的AppId,须要保障此AppId必须与你配置的QQ的AppId保持一致,否则回调会异样; 如果是Gradle集成,无需本人手动配置上述内容,ShareSDK会主动依据您的配置生成内容,防止本人配置谬误,如果gradle还是提醒勾销,能够删除build目录,从新加载即可; Android端Google登录提醒外部谬误?google开发者后盾,须要配置签名信息,这个谬误是因为您在google开发者后盾中的签名配置与您的app的不统一导致的,留神google配置的格局是SHA1,不须要去掉冒号; Android端Facebook想要分享胜利,须要做哪些内容Facebook,须要先申请利用,失去key,具体步骤查看链接:链接; 须要留神的是一些开关的关上,和回调地址的配置;配置完之后,将key配置到我的项目中,ShareSDK文档中有阐明,配置完即可分享; Android端ShareSDK的界面怎么删除不须要的平台离线集成,能够间接删除Jar包的形式即可,ShareSDK结尾的jar包,除了ShareSDK-core这个jar不能删除,其余的按须要的删除即可; Gradle集成的形式,是您在MobSDK下的ShareSDK外面加了什么平台,它就会有什么平台,具体参数能够参考Demo中的MobSDK.gradle文件,这里有全量的平台配置; Android端SDK配置第三方key的形式我认为第三方key的配置,配置在xml中,或者gradle中配置不平安,有其余的配置形式吗? A11.ShareSDK提供了三种配置形式,一是在ShareSDK后盾配置,二是在客户端中代码配置,三是惯例在xml中或者gradle文件中配置,SDK的拜访优先级顺次递加,也就是说如果您在ShareSDK后盾配置了,就不会拜访代码中和xml中的配置参数了; 具体配置查看文档:第三方平台初始化配置; Android端是否能够在App中不同中央显示不同的平台ShareSDK的OnekeyShare提供了接口,能够暗藏某个平台,oks.addHiddenPlatform(QQ.NAME);,比方这句就是暗藏QQ,想要暗藏其余的平台反复调用即可,留下您想留下的平台即可; Android端OnekeyShare分享,不同平台分享不同内容OnekeyShare的分享有提供接口,能够自定义某个平台分享的内容不同,具体详情见链接:链接 Android端ShareSDK的默认onekeyshare的回调如何批改在oks.show之前增加代码,本人能够管制,留神oncomplete中是子线程,给提醒的话须要传到UI线程中增加提醒; oks.setCallback(new PlatformActionListener() { @Override public void onComplete(Platform platform, int i, HashMap<String, Object> hashMap) { } @Override public void onError(Platform platform, int i, Throwable throwable) { } @Override public void onCancel(Platform platform, int i) { }});Android端OnekeyShare分享UI界面的自定义配置private void showShare(String platform) { final OnekeyShare oks = new OnekeyShare(); //指定分享的平台,如果为空,还是会调用九宫格的平台列表界面 if (platform != null) { oks.setPlatform(platform); } //去除分享正在后盾的提醒 oks.setDisappearShareToast(true); //敞开一键分享默认ui oks.setSilent(true); // 暗藏QQ平台不显示(想暗藏什么平台,填写什么平台,能够屡次调用) oks.addHiddenPlatform(QQ.NAME); ............. //启动分享 oks.show(MobSDK.getContext());}Android端OnekeyShare分享是否能够不要九宫格页面能够的,在onekeyshare分享的代码中加上您先独自调用的参数即可;eg:oks.setPlatform(QQ.NAME);加上这句就是独自分享到QQ; ...

March 28, 2023 · 4 min · jiezi

关于android:MobTech如何选择应用内广告SDK产品

利用内广告是一种在挪动利用中展现广告的形式,能够帮忙开发者进步利用支出和用户体验。然而,利用内广告的成果和品质取决于抉择的广告平台。那么,如何抉择一个优良的利用内广告平台呢?MobTech是寰球当先的综合性智能科技企业,以数据利用为主导,交融顶尖的大数据、云计算、人工智能等多元先进技术,为寰球多个国家和地区的企业、开发者和机构提供商业智能解决方案、App经营赋能计划、企业级AI智能计划、数据征询钻研等服务。 作为挪动开发者服务平台的领导者,MobTech提供了多种SDK,涵盖深度链接、第三方登录分享、短信验证、音讯推送等性能,已累计帮忙近30万个开发者团队升高开发成本,进步集成效率,构建最贴心的一站式服务平台。 其中,利用内广告SDK是MobTech为开发者提供的业余广告变现解决方案,具备以下劣势: 更高的广告收益:依靠于MobTech的海量数据及全域标签体系,通过“千人千故事”的智能举荐逻辑,爱护用户隐衷的同时向其精准展现感兴趣的广告,最大限度晋升变现效率。丰盛的广告模式:丰盛多样且吸引人的广告款式,包含开屏、插屏、Banner、原生、视频、激励、Push等,能够依据利用场景和用户爱好进行灵便组合,晋升用户体验和点击率。海量的广告资源:领有泛滥的优质广告主搭档,笼罩游戏、快消、金融、电商、出行、房产、教育等各类垂直行业,确保广告领有较高的填充率和转化率。可控的广告内容:全维度广告审核体系、严格的反作弊机制、反对多维度的自主屏蔽,帮忙开发者管制广告内容,防止因广告内容导致用户散失,保障流量生态衰弱。24小时贴心服务:业余服务团队,响应疾速,业内口碑当先,24小时全天服务,让开发者安枕无忧。

March 27, 2023 · 1 min · jiezi

关于android:ShareSDK-Android-第三方平台分享参数说明

 尽管ShareSDK尽可能屏蔽了不同社交平台间接口api差别,然而分享接口须要传递的差别仍然会因平台而异,本文将以列表的模式展现不同平台的分享参数(ShareParams)的字段要求,以不便开发者应用时翻阅。 留神没有表明可选的就是必填参数,不能为null或者空字符串,另一种状况是例如有imageUrl(”网络图片链接”)、imagePath(“/sdcard/abc.jpg”)、imageData(bitmap)是三选一。 国内平台新浪微博新浪微博反对分享文字、本地图片、网络图片 参数阐明 text:140字符以内 image:web分享ShareSDK不做限度间接提交给微博解决,微博客户端分享图片不能大于2M,仅反对JPEG、GIF、PNG格局; 注:微博分享链接是将链接写到setText内:eg:setText(“分享文本 http://mob.com”); ImageArray String类型图片数组,可传手机本地图片门路和图片链接,分享多图的时候须要将Url参数正文掉,否则会默认分享链接; 分享文本 text   留神:以下分享类型必须有新浪微博客户端才能够分享,如果imagePath和imageUrl同时存在,imageUrl将被疏忽; 分享图文 text imagePath imageUrl imageData 分享本地视频 FilePath("/sdcard/video.MP4") text("文本") 分享微博linkcard款式,成果如图下图所示,具体实现步骤能够点击查看这里; 腾讯微博腾讯微博反对分享文字、本地图片、网络图片和经纬度信息 参数阐明 text:最多140个字字符 image:图片最大4M 分享文本 text latitude(可选) longitude(可选) 分享图文 text imagePath latitude(可选) longitude(可选) imageUrl ImageArray 2.5.0当前的版本新增分享多张图片的性能ImageArray。 因为腾讯微博分享网络图片并不属于高级接口,因而imageUrl优先级高于imagePath,这就是说,如果imagePath和imageUrl同时存在,imagePath将被疏忽。 QQ空间提醒:必须须要QQ客户端才能够分享 QQ空间反对分享文字和图文 参数阐明 title:最多200个字符 text:最多600个字符 分享视频 FilePth("/sdcard/视频.mp4") ShareType(platform.SHARE\_VIDEO) 分享文本 text ShareType(platform.SHARE\_TEXT) 分享网页 text imagePath title titleUrl ShareType(platform.SHARE\_WEBPAGE) imageUrl 分享图片 imagePath ShareType(platform.SHARE\_IMAGE) imageUrl 微信(好友、朋友圈、珍藏)提醒: 1.必须须要客户端才能够分享; 2.微信客户端版本从6.7.2以上开始,勾销分享提醒分享胜利;即勾销分享和分享胜利都返回胜利事件; 3.Android11及之后的版本,微信分享图片不反对用imageData(bitmap)接口设置参数; 绕过审核只对微信好友、微信朋友圈无效 微信分享如果是绕过审核(配置信息BypassApproval属性设置为true为绕过审核),微信朋友圈能够分享单张图片或者图片与文字一起分享,微信好友能够进行文字或者单张图片进行分享,分享回调不会正确回调。 不绕过审核,微信三个平台中,好友的性能最残缺,朋友圈不能分享利用,珍藏不能分享利用,表格下以好友为例子: 参数阐明 title:512Bytes以内 text:10KB以内 imageData:10M以内 imagePath:10M以内(传递的imagePath门路不能超过10KB) imageUrl:10KB以内 musicUrl:10KB以内 url:10KB以内(MobSDK没有对参数另做限度,参数限度详细情况能够参考微信官网的限度详情点击这里查看) ...

March 27, 2023 · 4 min · jiezi

关于android:LeetCode-周赛-338贪心-埃氏筛-欧氏线性筛-前缀和-二分查找-拓扑排序

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。大家好,我是小彭。 上周末是 LeetCode 第 338 场周赛,你加入了吗?这场周赛笼罩的知识点很多,第四题称得上是近期几场周赛的天花板。 小彭的技术交换群 02 群来了,公众号回复 “加群” 退出咱们~ 目录2599. K 件物品的最大和(Easy) 贪婪、模仿 $O(1)$2600. 质数减法运算(Medium) 题解一:暴力枚举 + 二分查找 $O(U\sqrt{U} + nlgU)$题解二:Eratosthenes 埃氏筛 + 二分查找 $O(UlgU + nlgU)$题解三:Euler 欧氏线性筛 + 二分查找 $O(U + nlgU)$2601. 使数组元素全副相等的起码操作次数 前缀和 + 二分查找 $O(nlgn + qlgn)$2602. 收集树中金币(Hard) 拓扑排序 + 模仿 $O(n)$ 2599. K 件物品的最大和(Easy)题目地址https://leetcode.cn/problems/k-items-with-the-maximum-sum/des... 题目形容袋子中装有一些物品,每个物品上都标记着数字  1 、0  或  -1 。 给你四个非负整数  numOnes 、numZeros 、numNegOnes  和  k 。 袋子最后蕴含: numOnes  件标记为  1  的物品。numZeroes  件标记为  0  的物品。numNegOnes  件标记为  1  的物品。现打算从这些物品中恰好选出  k  件物品。返回所有可行计划中,物品上所标记数字之和的最大值。 ...

March 27, 2023 · 7 min · jiezi

关于android:预约直播3月30日下周四应用促活大揭秘快速提升DAU

【导读】 日常经营过程中,音讯推送是App触达用户的罕用伎俩,无论是新性能的告诉,还是流动的揭示,都能够通过推送告知用户。千人千面的个性化推送,对于晋升用户粘性、用户转化等指标都具备显著正向成果。越来越多的利用抉择华为Push用户增长服务作为拉新、促活的首选渠道,他们抉择的理由是什么?他们又是如何继续晋升用户月活量级并无效促成后端转化的? 本期直播《高效促活明码,“推”动用户快速增长》邀请天眼查做客直播间,介绍天眼查与华为Push用户增长服务的单干历程,分享华为Push用户增长服务的丰盛款式、千人千面的投放策略以及高效的促活技巧与成果。诚邀您进入直播间,一起探讨增长秘籍。 【直播预报】 工夫:2023年3月30日16:18 【直播平台】: 【特邀嘉宾】 刘树维,天眼查用户增长负责人 负责天眼查用户增长相干工作,通过兼顾站内外资源经营,实现用户增长。 Winify,华为Push用户增长服务产品经理 负责华为推送用户增长服务的产品相干工作,为App提供更便捷、更精准的用户触达能力。 Zora,华为Push用户增长服务经营经理 有丰盛的互联网经营及用户增长教训,善于策略优化以驱动增长和变现。 【直播看点】 1、解密唤醒缄默用户,DAU呈10倍速增长的办法! 2、如何通过3个经营动作,让点击率晋升400%? 【报名形式】 形式一 扫码填写问卷报名,收费获取专属咨询服务 形式二 扫码关注,预约直播 【直播抽奖】 进入直播间参加弹幕互动的小伙伴,有机会抽取精美礼品,不要错过哦! HUAWEI FreeBuds 4E 真无线耳机 华为手环 7 NFC版 3月30日 16:18 直播嘉宾为你现场答疑 点击官网,理解华为Push用户增长服务:https://developer.huawei.com/consumer/cn/userdevelopmentservi...

March 27, 2023 · 1 min · jiezi

关于android:教你如何在-Andorid-上使用OpenAI-API-调用ChatGpt

前言当初Chat GPT性能越来越强了,简直你想问理论问题它都能给你答复。正好,小组结课的 Android我的项目 有一个解梦的性能。正好调用chatGpt的Api来实现。上面就来简略实现在Andorid我的项目中打造一个繁难的聊天机器人。 先贴个成果, 还没进行丑化: 1.创立一个Andorid我的项目这里就不在具体地介绍如何创立一个Andorid我的项目了。谷歌上很多文章,比方官网示例:https://developer.android.com/training/basics/firstapp/creati... 2.在 build.gradle 中增加依赖这是用到的依赖 implementation 'com.google.android.material:material:1.7.0'implementation 'com.android.volley:volley:1.2.0'implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.3'compileOnly 'org.projectlombok:lombok:1.18.4'annotationProcessor 'org.projectlombok:lombok:1.18.4'implementation 'org.apache.commons:commons-lang3:3.6'3.在 AndroidManifest.xml 中增加联网权限<uses-permission android:name="android.permission.INTERNET"/>4. 注册OpenAI api来到 OpenAI api 注册账号,并生成 SECRET KEY 记得保留好,之后会用到。 5.编写xml界面文件在res/layout下新建activity_chat.xml文件 <?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/grey"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/idTILQuery" android:layout_alignParentTop="true" android:padding="5dp" android:layout_marginTop="5dp" android:layout_marginStart="5dp" android:layout_marginEnd="5dp" android:layout_marginBottom="5dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!-- text view for displaying question--> <TextView android:id="@+id/idTVQuestion" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="30dp" android:padding="4dp" android:text="Question" android:textColor="@color/purple_700" android:textSize="17sp"/> <!-- text view for displaying response--> <TextView android:id="@+id/idTVResponse" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="5dp" android:padding="4dp" android:text="Response" android:textColor="@color/purple_700" android:textSize="15sp"/> </LinearLayout> </ScrollView> <!-- text field for asking question--> <com.google.android.material.textfield.TextInputLayout android:id="@+id/idTILQuery" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_margin="5dp" app:endIconMode="custom" app:endIconDrawable="@drawable/send" android:hint="Enter your query" android:padding="5dp" android:textColorHint="@color/black" app:hintTextColor="@color/black"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/idEdtQuery" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/grey" android:ems="10" android:imeOptions="actionSend" android:importantForAutofill="no" android:inputType="textEmailAddress" android:textColor="@color/black" android:textColorHint="@color/black" android:textSize="14sp" /> </com.google.android.material.textfield.TextInputLayout></RelativeLayout>一个简略的页面如下 ...

March 25, 2023 · 4 min · jiezi

关于android:Moblink节省开发者时间精力和公司成本

在当今社会,挪动利用曾经成为人们日常生活中不可短少的工具。它们能够让咱们随时随地地拜访互联网、获取信息、沟通交流等。然而,在挪动利用的推广过程中,开发者和公司面临着很多挑战。例如: 如何让用户从Web端间接关上App指定页面,而不是下载页面或首页?如何让用户在首次装置App后,可能复原之前浏览过的内容或场景?如何让用户在Web页面上点击任意内容,都能间接跳转到App相应页面?如何实时批改Web页面上跳转到App的按钮款式,以适应不同场景和需要?为了解决这些问题,开发者须要破费大量的工夫和精力来编写简单的代码,并且须要思考各种兼容性和安全性问题。而对于公司来说,这也意味着更高的人力老本和经营危险。为了防止这些麻烦,开发者和公司须要一种挪动深度链接解决方案,能够让Web与App之间实现无缝跳转,进步用户转化率、下载量和活跃度。而Moblink就是一种这样的解决方案。Moblink对于开发者和公司来说都有很多劣势。以下是一些次要的劣势: 节俭开发工夫:Moblink提供了对立的接口和简略的操作,只须要一次集成就能够应用所有性能。而且Moblink反对多种开发平台和框架,并且兼容40多种支流社交平台。升高经营老本:Moblink提供了收费的服务,并且包体只有600kb。而且Moblink不须要服务器端或第三方服务反对,能够保证数据的平安和稳固。进步用户体验:Moblink能够让用户从Web端间接关上App指定页面,而不是下载页面或首页。这样能够让用户更快地获取想要的内容,并且进步用户对App的趣味和信赖。减少用户转化率:Moblink能够让用户在首次装置App后,可能复原之前浏览过的内容或场景。这样能够让新用户感到相熟和称心,并且进步留存率和活跃度。晋升分享效率:Moblink能够让用户在Web页面上点击任意内容,都能间接跳转到App相应页面。这样能够让用户更不便地分享和流传App的内容,并且进步App的知名度和口碑。

March 24, 2023 · 1 min · jiezi

关于android:让Web和App无缝链接的移动深度链接方案

在挪动互联网时代,Web和App之间的链接是一个常见而又重要的需要。例如,当用户在微信、微博等社交平台上看到一个乏味的内容时,可能会点击链接跳转到对应的App或者网页上查看更多详情。然而,传统的URL链接存在很多问题和局限性,比方: 如果用户没有装置指标App,那么跳转到网页上会导致用户体验降落,同时也会升高App的装置率和留存率。如果用户曾经装置了指标App,那么跳转到App上可能会失落原始场景信息,比方分享者、内容ID等,导致用户无奈间接进入到想要查看的页面。如果用户在不同设施上应用同一个URL链接,那么可能会呈现不统一或者谬误的后果。为了解决这些问题,MobTech公司推出了一种挪动深度链接解决方案——MobLink。MobLink能够实现Web与App之间的无缝链接,并且可能还原用户在不同场景下的拜访状态。具体来说,MobLink有以下几个特点: 智能辨认:MobLink能够依据用户是否装置了指标App以及设施类型等因素主动抉择适合的跳转形式。如果用户曾经装置了指标App,则间接关上App并进入到对应页面;如果没有装置,则疏导用户下载并关上App,并且保留原始场景信息。场景还原:MobLink能够通过生成惟一标识符来记录用户在不同场景下拜访内容时所携带的参数信息。例如,在社交平台上分享一个商品详情页面时,能够将分享者、商品ID等信息作为参数传递给MobLink,并生成一个短链供其余用户点击。当其余用户点击该短链时,MobLink能够依据参数信息还原出分享者、商品ID等信息,并将其传递给指标App或网页。数据统计:MobLink能够提供残缺清晰的数据统计性能,帮忙开发者剖析和优化挪动深度链接成果。例如,在后盾治理平台上能够查看每个短链被点击次数、起源渠道、设施类型、地理位置等数据,并且能够依照时间段、自定义标签等维度进行筛选和比照。总之,MobLink是一种可能实现Web与App无缝链接并且可能还原挪动场景状态的解决方案。它能够帮忙开发者进步挪动利用开发效率和成果,并且晋升用户体验和满意度。

March 24, 2023 · 1 min · jiezi

关于android:如何使用ShareSDK快速实现Android-APP的社会化分享登录功能

社会化分享登录性能是许多Android App开发者都须要实现的一个需要,它能够让用户通过第三方平台(如微信、QQ、微博等)进行分享和受权,进步用户体验和活跃度。然而,如果要本人集成各个平台的SDK和接口,不仅须要破费大量的工夫和精力,还要面对各种兼容性和更新问题。有没有一种更简略高效的形式呢? 答案是有的,那就是应用ShareSDK。ShareSDK是MobTech公司提供的一种社会化分享登录组件,它曾经为咱们封装了40多个支流平台的分享与受权等性能,只须要几行代码就能够轻松集成到咱们的App中。而且,ShareSDK还提供了丰盛的文档、示例、插件和技术支持,让咱们能够更不便地应用和定制它。 那么,如何在咱们的Android App中集成ShareSDK呢?其实很简略,只须要以下几个步骤:在MobTech官网注册开发者账号,并获取AppKey和AppSecret。在我的项目Gradle文件中注册MobSDK插件,并配置AppKey和AppSecret。在我的项目Manifest文件中增加必要的权限和Activity。在我的项目代码中初始化ShareSDK,并调用相干API进行分享或受权。在MobTech后盾配置各个平台的参数,并测试成果。 就这么简略!通过应用ShareSDK,咱们能够大大节俭开发工夫和老本,同时也能够享受到更多劣势:反对40多个支流平台的分享与受权等性能反对多种UI款式和自定义界面反对多种数据统计和剖析反对多种平安机制和加密算法反对多语言和国际化反对最新版本的Android Studio和Gradle继续更新保护并提供技术支持 如果你对ShareSDK感兴趣或想理解更多详情,请拜访MobTech官网(www.mob.com)

March 24, 2023 · 1 min · jiezi

关于android:MobPush-Android-厂商通道回执配置指南

华为接入厂商通道后,华为通道的达到率统计笼罩用户点击华为弹窗推送告诉的场景,未点击局部暂未笼罩,您可在华为端设置音讯回执,便于挪动推送更好的统计推送数据,具体设置办法请参见:音讯回执。 开明回执需配置回调地址:https://report.push.mob.com/huawei/report 魅族在魅族推送平台的利用列表,单击关上利用,进入配置管理>回执治理页面。 设置回执地址为:http://report.push.mob.com/meizu/report否则可能会收不到推送音讯或无奈统计音讯数据。 留神:魅族此回执地址需是http申请

March 24, 2023 · 1 min · jiezi

关于android:自定义图片缩放布局可放大缩小

主体 public class ZoomImageView extends ImageView implements ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener { private static final String TAG = ZoomImageView.class.getSimpleName(); public static final float SCALE_MAX = 4.0f; private static final float SCALE_MID = 2.0f; /** * 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0 */ private float initScale = 1.0f; private boolean once = true; /** * 用于寄存矩阵的9个值 */ private final float[] matrixValues = new float[9]; /** * 缩放的手势检测 */ private ScaleGestureDetector mScaleGestureDetector = null; private final Matrix mScaleMatrix = new Matrix(); /** * 用于双击检测 */ private GestureDetector mGestureDetector; private OnZoomImageViewSingleClickListener listener; /** * @date:2017/11/16/016 * @author:平sir * @desc: 初始化拦挡单击事件的接口对象 */ public void setListener(OnZoomImageViewSingleClickListener listener) { this.listener = listener; } public OnZoomImageViewSingleClickListener getListener() { return listener; } private boolean isAutoScale; private int mTouchSlop; private float mLastX; private float mLastY; private boolean isCanDrag; private int lastPointerCount; private boolean isCheckTopAndBottom = true; private boolean isCheckLeftAndRight = true; public ZoomImageView(Context context) { this(context, null); } public ZoomImageView(Context context, AttributeSet attrs) { super(context, attrs); super.setScaleType(ScaleType.MATRIX); mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { if (isAutoScale) return true; float x = e.getX(); float y = e.getY(); if (getScale() < SCALE_MID) { ZoomImageView.this.postDelayed( new AutoScaleRunnable(SCALE_MID, x, y), 16); isAutoScale = true; } else if (getScale() >= SCALE_MID && getScale() < SCALE_MAX) { ZoomImageView.this.postDelayed( new AutoScaleRunnable(SCALE_MAX, x, y), 16); isAutoScale = true; } else { ZoomImageView.this.postDelayed( new AutoScaleRunnable(initScale, x, y), 16); isAutoScale = true; } return true; } }); mScaleGestureDetector = new ScaleGestureDetector(context, this); this.setOnTouchListener(this); } /** * 主动缩放的工作 * * @author zhy */ private class AutoScaleRunnable implements Runnable { static final float BIGGER = 1.07f; static final float SMALLER = 0.93f; private float mTargetScale; private float tmpScale; /** * 缩放的核心 */ private float x; private float y; /** * 传入指标缩放值,依据目标值与以后值,判断应该放大还是放大 * * @param targetScale */ public AutoScaleRunnable(float targetScale, float x, float y) { this.mTargetScale = targetScale; this.x = x; this.y = y; if (getScale() < mTargetScale) { tmpScale = BIGGER; } else { tmpScale = SMALLER; } } @Override public void run() { // 进行缩放 mScaleMatrix.postScale(tmpScale, tmpScale, x, y); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); final float currentScale = getScale(); // 如果值在非法范畴内,持续缩放 if (((tmpScale > 1f) && (currentScale < mTargetScale)) || ((tmpScale < 1f) && (mTargetScale < currentScale))) { ZoomImageView.this.postDelayed(this, 16); } else // 设置为指标的缩放比例 { final float deltaScale = mTargetScale / currentScale; mScaleMatrix.postScale(deltaScale, deltaScale, x, y); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); isAutoScale = false; } } } @SuppressLint("NewApi") @Override public boolean onScale(ScaleGestureDetector detector) { float scale = getScale(); float scaleFactor = detector.getScaleFactor(); if (getDrawable() == null) return true; /** * 缩放的范畴管制 */ if ((scale < SCALE_MAX && scaleFactor > 1.0f) || (scale > initScale && scaleFactor < 1.0f)) { /** * 最大值最小值判断 */ if (scaleFactor * scale < initScale) { scaleFactor = initScale / scale; } if (scaleFactor * scale > SCALE_MAX) { scaleFactor = SCALE_MAX / scale; } /** * 设置缩放比例 */ mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY()); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); } return true; } /** * 在缩放时,进行图片显示范畴的管制 */ private void checkBorderAndCenterWhenScale() { RectF rect = getMatrixRectF(); float deltaX = 0; float deltaY = 0; int width = getWidth(); int height = getHeight(); // 如果宽或高大于屏幕,则管制范畴 if (rect.width() >= width) { if (rect.left > 0) { deltaX = -rect.left; } if (rect.right < width) { deltaX = width - rect.right; } } if (rect.height() >= height) { if (rect.top > 0) { deltaY = -rect.top; } if (rect.bottom < height) { deltaY = height - rect.bottom; } } // 如果宽或高小于屏幕,则让其居中 if (rect.width() < width) { deltaX = width * 0.5f - rect.right + 0.5f * rect.width(); } if (rect.height() < height) { deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height(); } mScaleMatrix.postTranslate(deltaX, deltaY); } /** * 依据以后图片的Matrix取得图片的范畴 * * @return */ private RectF getMatrixRectF() { Matrix matrix = mScaleMatrix; RectF rect = new RectF(); Drawable d = getDrawable(); if (null != d) { rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); matrix.mapRect(rect); } return rect; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } @Override public boolean onTouch(View v, MotionEvent event) { /** * 设置拦挡单击事件 */ mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() { @Override public boolean onSingleTapConfirmed(MotionEvent motionEvent) { if (listener != null) listener.onClick(); return false; } @Override public boolean onDoubleTap(MotionEvent e) { if (isAutoScale) return true; float x = e.getX(); float y = e.getY(); if (getScale() < SCALE_MID) { ZoomImageView.this.postDelayed( new AutoScaleRunnable(SCALE_MID, x, y), 16); isAutoScale = true; } else if (getScale() >= SCALE_MID && getScale() < SCALE_MAX) { ZoomImageView.this.postDelayed( new AutoScaleRunnable(SCALE_MAX, x, y), 16); isAutoScale = true; } else { ZoomImageView.this.postDelayed( new AutoScaleRunnable(initScale, x, y), 16); isAutoScale = true; } return true; } @Override public boolean onDoubleTapEvent(MotionEvent motionEvent) { return false; } }); if (mGestureDetector.onTouchEvent(event)) return true; mScaleGestureDetector.onTouchEvent(event); float x = 0, y = 0; // 拿到触摸点的个数 final int pointerCount = event.getPointerCount(); // 失去多个触摸点的x与y均值 for (int i = 0; i < pointerCount; i++) { x += event.getX(i); y += event.getY(i); } x = x / pointerCount; y = y / pointerCount; /** * 每当触摸点发生变化时,重置mLasX , mLastY */ if (pointerCount != lastPointerCount) { isCanDrag = false; mLastX = x; mLastY = y; } lastPointerCount = pointerCount; RectF rectF = getMatrixRectF(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (rectF.width() > getWidth() || rectF.height() > getHeight()) { getParent().requestDisallowInterceptTouchEvent(true); } break; case MotionEvent.ACTION_MOVE: if (rectF.width() > getWidth() || rectF.height() > getHeight()) { getParent().requestDisallowInterceptTouchEvent(true); } float dx = x - mLastX; float dy = y - mLastY; if (!isCanDrag) { isCanDrag = isCanDrag(dx, dy); } if (isCanDrag) { if (getDrawable() != null) { // if (getMatrixRectF().left == 0 && dx > 0) // { // getParent().requestDisallowInterceptTouchEvent(false); // } // // if (getMatrixRectF().right == getWidth() && dx < 0) // { // getParent().requestDisallowInterceptTouchEvent(false); // } isCheckLeftAndRight = isCheckTopAndBottom = true; // 如果宽度小于屏幕宽度,则禁止左右挪动 if (rectF.width() < getWidth()) { dx = 0; isCheckLeftAndRight = false; } // 如果高度小雨屏幕高度,则禁止高低挪动 if (rectF.height() < getHeight()) { dy = 0; isCheckTopAndBottom = false; } mScaleMatrix.postTranslate(dx, dy); checkMatrixBounds(); setImageMatrix(mScaleMatrix); } } mLastX = x; mLastY = y; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: lastPointerCount = 0; break; } return true; } /** * @date:2017/11/16/016 * @author:平sir * @desc: 定义接口,用于拦挡单击事件 */ public interface OnZoomImageViewSingleClickListener { void onClick(); } /** * 取得以后的缩放比例 * * @return */ public final float getScale() { mScaleMatrix.getValues(matrixValues); return matrixValues[Matrix.MSCALE_X]; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewTreeObserver().addOnGlobalLayoutListener(this); } @SuppressWarnings("deprecation") @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver().removeGlobalOnLayoutListener(this); } @Override public void onGlobalLayout() { if (once) { Drawable d = getDrawable(); if (d == null) return; int width = getWidth(); int height = getHeight(); // 拿到图片的宽和高 int dw = d.getIntrinsicWidth(); int dh = d.getIntrinsicHeight(); float scale = 1.0f; // 如果图片的宽或者高大于屏幕,则缩放至屏幕的宽或者高 if (dw > width && dh <= height) { scale = width * 1.0f / dw; } if (dh > height && dw <= width) { scale = height * 1.0f / dh; } // 如果宽和高都大于屏幕,则让其按按比例适应屏幕大小 if (dw > width && dh > height) { scale = Math.min(width * 1.0f / dw, height * 1.0f / dh); } initScale = scale; mScaleMatrix.postTranslate((float) (width - dw) / 2, (float) (height - dh) / 2); mScaleMatrix.postScale(scale, scale, (float) getWidth() / 2, (float) getHeight() / 2); // 图片挪动至屏幕核心 setImageMatrix(mScaleMatrix); once = false; } } /** * 挪动时,进行边界判断,次要判断宽或高大于屏幕的 */ private void checkMatrixBounds() { RectF rect = getMatrixRectF(); float deltaX = 0, deltaY = 0; final float viewWidth = getWidth(); final float viewHeight = getHeight(); // 判断挪动或缩放后,图片显示是否超出屏幕边界 if (rect.top > 0 && isCheckTopAndBottom) { deltaY = -rect.top; } if (rect.bottom < viewHeight && isCheckTopAndBottom) { deltaY = viewHeight - rect.bottom; } if (rect.left > 0 && isCheckLeftAndRight) { deltaX = -rect.left; } if (rect.right < viewWidth && isCheckLeftAndRight) { deltaX = viewWidth - rect.right; } mScaleMatrix.postTranslate(deltaX, deltaY); } /** * 是否是推动行为 * * @param dx * @param dy * @return */ private boolean isCanDrag(float dx, float dy) { return Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop; }}应用 ...

March 24, 2023 · 6 min · jiezi

关于android:为什么秒验是老年用户注册的最佳选择

随着挪动互联网的遍及,越来越多的老年用户开始应用各种挪动利用,享受便捷的生存服务。然而,对于老年用户来说,注册登录这个看似简略的步骤却是一个很大的阻碍。因为他们往往不相熟手机操作,容易遗记明码,或者对短信验证码感到困惑和不安。 为了解决这个问题,并让老年用户可能更轻松地应用挪动利用,MobTech公司推出了秒验服务。秒验是一种基于运营商网关取号的手机号验证服务。它能够帮忙开发者实现以下指标: 简化注册登录流程:秒验通过SDK与运营商网络通信来采集用户手机号码,在取得用户批准受权后即可实现验证,无需期待或输出验证码优化老年用户体验:秒验操作简略快捷,只需一键受权即可实现验证,无需记住或输出明码,也无需放心验证码提早、失落、谬误等问题进步老年用户转化率:秒验能够无效缩小老年用户在注册登录过程中遇到的艰难和挫折感,在注册登录/拉新留存等场景中进步转化成果保障老年用户安全性:秒验基于运营商网关取号技术,保障了手机号码的真实性和安全性,并且反对三网手机号、虚构运营商号、携号转网等状况 总之,秒验是一种让老年用户注册更简略的手机号验证服务。它能够简化注册登录流程,优化老年用户体验,并进步老年用户转化率和安全性。

March 23, 2023 · 1 min · jiezi

关于android:如何用秒验提升用户体验和转换率

手机号验证是挪动利用开发中常见的需要,它能够用于用户注册、登录、身份认证等场景。目前,市场上次要的手机号验证形式是短信验证码,但这种形式存在一些问题,例如:提早:短信验证码须要期待运营商发送和用户接管,可能会有几秒到几十秒不等的提早费用:短信验证码须要向运营商领取费用,对于大量用户或高频次验证的利用来说,费用较高用户散失:短信验证码须要用户输出或复制粘贴,操作繁琐,可能导致用户放弃或转化率升高 为了解决这些问题,MobTech公司推出了一种新型的手机号验证服务——秒验。秒验是一种基于运营商网关取号的服务,它能够实现以下性能:运营商网关取号:秒验通过SDK与运营商的网络通信来采集用户手机号码,无需用户输出或发送短信一键验证:秒验在取得用户批准受权后,即可实现手机号码的验证,无需期待或输出验证码获取手机号信息:秒验在实现验证后,能够返回以后受权用户的手机号码等信息给利用客户端和服务端 秒验相比于短信验证码有以下劣势:晋升经营价值:操作简略快捷,有利于进步注册登录/拉新留存成果晋升用户体验:一键验证不便疾速,优化用户体验和满意度灵便配置:可依据产品需要自在决定产品流程和配置项缩小客户端用户流失率:均匀3秒内实现验证,比短信验证码快10倍反对多种场景:只需一次开发接入即可反对三网手机号、虚构运营商号、反对携号转网 如果开发者想要应用秒验服务,须要在MobTech开发者后盾提交审核。审核工夫个别为工作日当天或下个工作日。审核通过后即可下载SDK并集成到利用中。 综上所述,秒验是一种基于运营商网关取号的手机号验证服务,它能够解决短信验证码存在的问题,并带来更多的劣势和价值。倡议开发者尝试应用并评估其成果。

March 23, 2023 · 1 min · jiezi

关于android:MobPush-Android-SDK-API

推送监听接口 (addPushReceiver)形容:增加推送监听,可监听接管到的自定义音讯(透传音讯)、告诉音讯、告诉栏点击事件、别名和标签变更操作。 /** * com.mob.pushsdk.MobPush.class * MobPush推送监听接口 * @param receiver 监听 */public static void addPushReceiver(MobPushReceiver receiver)示例代码 MobPushReceiver mobPushReceiver = new MobPushReceiver() { @Override public void onCustomMessageReceive(Context context, MobPushCustomMessage message) { //接管到自定义音讯(透传音讯) message.getMessageId();//获取工作ID message.getContent();//获取推送内容 } @Override public void onNotifyMessageReceive(Context context, MobPushNotifyMessage message) { //接管到告诉音讯 message.getMobNotifyId();//获取音讯ID message.getMessageId();//获取工作ID message.getTitle();//获取推送题目 message.getContent();//获取推送内容 } @Override public void onNotifyMessageOpenedReceive(Context context, MobPushNotifyMessage message) { //告诉被点击事件 message.getMobNotifyId();//获取音讯ID message.getMessageId();//获取工作ID message.getTitle();//获取推送题目 message.getContent();//获取推送内容 } @Override public void onTagsCallback(Context context, String[] tags, int operation, int errorCode) { //标签操作回调 //tags: RegistrationId已增加的标签 //operation: 0获取标签 1设置标签 2删除标签 //errorCode: 0操作胜利 非0操作失败 } @Override public void onAliasCallback(Context context, String alias, int operation, int errorCode) { //别名操作回调 //alias: RegistrationId对应的别名 //operation: 0获取别名 1设置别名 2删除别名 //errorCode: 0操作胜利 非0操作失败 } };移除推送监听接口 (removePushReceiver)形容:移除告诉监听,与addPushReceiver()对应,增加推送监听后,在敞开界面时调用进行移除,移除之前增加过的推送监听。 ...

March 23, 2023 · 4 min · jiezi

关于android:MobPush-Android-SDK合规指南

确保APP有《隐衷政策》您须要确保App有《隐衷政策》,并且在用户首次启动App时就弹出《隐衷政策》获得用户批准。 增加MobTech隐衷协定MobPushSDK 隐衷政策您务必告知用户您抉择MobSDK服务,请在《隐衷政策》中减少如下参考条款: MobPushSDK 咱们应用了第三方(上海游昆信息技术有限公司,以下称“MobTech”)MobTech MobPushSDK服务为您提供 音讯推送性能。为了顺利实现该性能,您须要受权MobTechSDK提供对应的服务;在您受权后,MobTech将收集您相干的个人信息。对于MobTech所收集的信息品种、用处、个人信息爱护的规定及退出机制等,详见MobTech官网(www.mob.com)上的隐衷政策 (www.mob.com/about/policy)条款。 第三方 SDK 隐衷政策若通过MobPushSDK 同时集成了厂商通道,请在《隐衷政策》中减少对于厂商通道的隐衷政策阐明,内容如下: 小米推送 SDK 波及的个人信息类型:设施标识符(如 Android ID、OAID、GAID)、设施信息 应用目标:推送音讯 应用场景:在小米手机终端推送音讯时应用 第三方主体:北京小米挪动软件有限公司 数据处理形式:通过去标识化、加密传输及其他平安形式 官网链接:https://dev.mi.com/console/appservice/push.html 隐衷政策:https://dev.mi.com/console/doc/detail?pId=1822 华为 HMS SDK 波及的个人信息类型:利用根本信息、利用内设施标识符、设施的硬件信息、零碎根本信息和零碎设置信息 应用目标:推送音讯 应用场景:在华为手机终端推送音讯时应用 第三方主体:华为软件技术有限公司 数据处理形式:通过去标识化、加密传输及其他平安形式 官网链接:https://developer.huawei.com/consumer/cn/ 隐衷政策:https://developer.huawei.com/consumer/cn/doc/development/HMSC... 光荣推送 SDK 波及的个人信息类型:利用匿名标识 (AAID),利用 Token 应用目标:推送音讯 应用场景:在光荣手机终端推送音讯时应用 第三方主体:光荣终端有限公司 数据处理形式:通过去标识化、加密传输及其他平安形式 官网链接:https://developer.hihonor.com/cn/promoteService 隐衷政策:https://www.hihonor.com/cn/privacy/privacy-policy/ OPPO 推送 SDK 波及的个人信息类型:设施标识符(如 IMEI、ICCID、IMSI、Android ID、GAID)、利用信息(如利用包名、版本号和运行状态)、网络信息(如 IP 或域名连贯后果,以后网络类型) 应用目标:推送音讯 应用场景:在 OPPO 手机终端推送音讯时应用 第三方主体:广东欢太科技有限公司 数据处理形式:通过加密传输和解决的平安解决形式 官网链接:https://open.oppomobile.com/new/introduction?page_name=oppopush 隐衷政策:https://open.oppomobile.com/wiki/doc#id=10288 vivo 推送 SDK 波及的个人信息类型:设施信息 应用目标:推送音讯 应用场景:在 vivo 手机终端推送音讯时应用 第三方主体:广东天宸网络科技有限公司及未来受让经营 vivo 开放平台的公司 ...

March 23, 2023 · 1 min · jiezi

关于android:集成Health-Kit时因证书问题出现错误码50063的解决方案

一、问题形容及操作利用集成Health Kit SDK后,在华为手机上进行登录受权时,返回错误码50063。 1、查看相干错误码。‘50063’在Health Kit错误码中的形容是“装置的HMS Core APK版本不匹配,无奈调用接口。”提供的解决方案是“请装置最新版本的HMS Core(APK)后,再调用接口”。 2、依据文档中提供的解决方案,卸载了手机设施中的HMS Core APK,从新更新到最新版本后,仍返回错误码50063。 3、调用HuaweiApiAvailability#isHuaweiMobileServicesAvailable(Context context)接口,检测HMS Core (APK)在设施上是否胜利装置和集成时,返回后果1,示意在设施上没有发现HMS Core(APK),预期后果应该返回0。 4、应用‘adb logcat > log.txt’获取残缺日志,进行日志剖析。 二、起因剖析在日志中筛选“HMSSDK_”,能够看到要害日志“E/HMSSDK_X509CertUtil: Not include alias 052root”。 依据日志显示,是因为hmsrootcas.bks证书中没有发现052root信息,导致校验失败,从而引起登录失败。失常状况下,如果应用Maven仓集成SDK时,此hmsrootcas.bks证书文件会在打包时主动放到apk的assets目录下,个别不会呈现问题。 如果没有日志,也能够借助工具查看APK中的hmsrootcas.bks是否蕴含052root: 三、解决方案1、查看我的项目工程中的assets资源文件目录中是否存在hmsrootcas.bks文件,如果存在的话,能够删除,在打包时hmsrootcas.bks会主动打包到apk中。 2、如果assets资源文件目录中不存在hmsrootcas.bks文件或删除后,仍呈现此问题,能够手动集成蕴含052root信息的bks文件,具体操作如下: 1)拜访链接,下载SDK文件。 2)解压下载的文件,依据以下门路找到bks文件,并集成到我的项目主工程下的assets中:hmssdk-eclipse-6.9.0.300\Security-ssl\assets。仅搁置hmsrootcas.bks文件即可。 3)从新编译我的项目。 更多接入华为静止衰弱服务常见问题,请参见FAQ 理解更多详情>> 拜访华为开发者联盟官网 获取开发领导文档 华为挪动服务开源仓库地址:GitHub、Gitee 关注咱们,第一工夫理解 HMS Core 最新技术资讯~

March 23, 2023 · 1 min · jiezi

关于android:扫一扫原来这么简单

二维码辨认技术已广泛应用在挪动领取、实用工具、电商购物、社交通信等场景。然而,在理论生存中,二维码容易遇到距离远、暗光、强光、污损、含糊和大角度歪斜等简单场景,导致辨认艰难,扫码体验差。华为HMS Core 对立扫码服务(Scan Kit)为开发者们的APP带来一站式扫码解决方案,并且领有高识别率和疾速辨认等特点。 间隔太远、码图过小?在停车场扫码缴费、上课扫码签到、广告牌宣传等理论生存场景中,二维码的尺寸不一,个别的扫码性能需手动调节手机相机框与二维码的间隔直到适合的扫码大小,实属不便。对立扫码服务基于自研的深度学习算法模型,遇到远距离场景、码图过小、甚至肉眼无奈分辨的状况,反对自动检测放大,智能辨认。 多角度、光线不佳、含糊等简单场景无奈辨认?餐桌、共享单车、充电桩等设施上的二维码,易受环境或人为影响,导致污损、含糊、反光,无奈清晰展现,造成辨认艰难。对立扫码服务基于多项计算机视觉技术,能够大幅晋升简单场景识别率,对立扫码服务能够自动检测及旋转纠正,可能在辨认任意角度的同时保障准确率。 单个扫码效率低?在录入商品信息、快递信息等须要频繁扫码的场景中,个别的扫码性能辨认胜利后会主动跳转,操作不便。对立扫码服务为您带来间断扫码性能,对相机内间断呈现的二维码辨认检测,防止辨认胜利主动跳转的问题。同时,多码识别模式下,对立扫码服务最多可同时辨认不限品种的5个码,大幅晋升工作效率。 另外,HMS Core 对立扫码服务为助力开发者们构建晦涩的扫码体验,带来更加欠缺的性能: ① 反对辨认/生成13种支流码格局; ② 反对自定义扫码界面; ③ 反对剖析12个场景的码内容,提取结构化数据; ④ 提供内存 1.1M / 3.3M 两种SDK及4种不同类型的调用形式,安卓版本起码5行代码即可疾速接入。 上面是接入 HMS Core 对立扫码服务的开发步骤,以Default View Mode为例,只需简略的集成就可为利用构建扫码能力。 开发步骤1. 开发筹备具体筹备步骤可参考华为开发者联盟官网。 2. 集成筹备Default View Mode提供相机扫码和导入图片扫码两个性能,提供残缺的Activity,不须要您开发扫码界面。 留神:应用此种模式请确保您的利用没有敞开硬件加速,即“hardwareAccelerated”为“true”。否则在个别机型可能会呈现黑屏问题。 3. 业务流程应用Default View Mode的次要业务流程如下: 1) 用户关上App发动扫码申请。 2) 校验是否有相机权限。 3) 权限验证通过后,调用HMS Core SDK的startScan扫码接口,启动扫码界面。若须要满足最小权限和场景化触发要求,文件读取权限在用户点击后触发场景,须要设置谬误监听,检测到无文件读取权限,Scan Kit报错退出Default View。 4) 判断扫码页面启动状态。 5) HMS Core SDK回调利用的“onActivityResult”接口。 6) 依据扫码状态RESULT_CODE获取扫码后果:若SUCCESS返回后果给用户;若后果为ERROR_NO_READ_PERMISSION,须要利用被动申请文件读取权限,从新进入Default View。 7) App封装扫码后果返回给用户。 开发步骤1) (可选)依据理论需要创立扫码选项参数。 Scan Kit默认反对13种码制式,您也能够指定Scan Kit只扫描特定的码制式以进步扫码速度。例如,当仅须要检测QR码和DataMatrix码时,请依照以下示例构建HmsScanAnalyzerOptions对象。如果不限度检测码格局,您能够不创立HmsScanAnalyzerOptions对象。“1”为您设置的扫码题目款式参数,对应setViewType办法中的“var1”参数。 // “QRCODE_SCAN_TYPE”和“DATAMATRIX_SCAN_TYPE”示意只扫描QR和DataMatrix的码,setViewType设置扫码题目,0示意设置扫码题目为”扫描二维码/条码“,1示意设置扫码题目为”扫描二维码“,默认为0;setErrorCheck设置谬误监听,true示意监听谬误并退出扫码页面,false示意不上报谬误,仅查看到辨认后果后退出扫码页面,默认为falseHmsScanAnalyzerOptions options = new HmsScanAnalyzerOptions.Creator().setHmsScanTypes(HmsScan.QRCODE_SCAN_TYPE,HmsScan.DATAMATRIX_SCAN_TYPE).setViewType(1).setErrorCheck(true).create();2) 调用ScanUtil的静态方法startScan启动Default View扫码页面。用户能够应用相机扫码,也能够通过该页面的“导入图片”按钮检测图片中的码。 ...

March 22, 2023 · 1 min · jiezi

关于android:刷爆-LeetCode-周赛-337位掩码回溯同余分桶动态规划打家劫舍贪心

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。大家好,我是小彭。 上周末是 LeetCode 第 337 场周赛,你加入了吗?这场周赛第三题有点放水,如果依照题目的数据量来说最多算 Easy 题,但如果依照动静布局来做能够算 Hard 题。 小彭的技术交换群 02 群来了,公众号回复 “加群” 退出咱们~ 周赛概览2595.  奇偶位数(Easy) 题解一:模仿 $O(lgn)$题解二:位掩码 + bitCount $O(1)$2596.  查看骑士巡视计划(Medium) 题解一:模仿 $O(n^2)$2597.  漂亮子集的数目(Medium) 题解一:回溯 $O(2^n)$题解二:同余分组 + 动静布局 / 打家劫舍 $O(nlgn)$2598.  执行操作后的最大 MEX(Medium) 题解一:同余分组 + 贪婪 $O(n)$ 2595.  奇偶位数(Easy)题目地址https://leetcode.cn/problems/number-of-even-and-odd-bits/ 题目形容给你一个  正  整数  n 。 用  even  示意在  n  的二进制模式(下标从  0  开始)中值为  1  的偶数下标的个数。 用  odd  示意在  n  的二进制模式(下标从  0  开始)中值为  1  的奇数下标的个数。 返回整数数组  answer ,其中  answer = [even, odd] 。 ...

March 22, 2023 · 6 min · jiezi

关于android:Android性能优化ListView自适应性能问题

作者:京东物流 张振勇 ListView是Android中最罕用的视图之一,应用的频率仅仅次于几大根底布局,尽管因为应用性和扩展性等起因备受争议,且只管起初呈现了RecyclerView的代替计划,然而ListView依然宽泛地应用在咱们的我的项目中。 自从ListView出道至今,曾经不晓得衍生出了多少问题,然而很多人只关怀性能性能的实现,却极少关注ListView适度调用导致的性能问题。在理论我的项目中,即便你正确应用了ViewHolder机制来优化ListView性能,然而在某些场景下仍然会感觉卡顿重大,到底是什么起因导致的呢,咱们来剖析下 1 问题演示很多时候,咱们在应用ListView的时候,都是顺手写上一个layout\_height=”wrap\_content”或者layout\_height=”match\_parent”,十分惯例的写法,乍一看,并没有什么问题,尤其是性能实现上也是无可挑剔。 然而,就是layout\_height=”wrap\_content”这个属性是导致重大的性能问题的本源,上面以一个简略的例子阐明一下: 布局如上,接下来,假如ListView一共有5项,那么显示逻辑代码如下: 上面,咱们来看看log打印的状况: 数一数,一个是15次getView调用,其中6次convertView为null,残余9次convertView为复用,而ListView的数据源真正只有5项! 当然,为了场景的简单化,咱们先不思考ListView内容超过一屏幕的状况(也就是不思考其复用机制),所以咱们期待的状况应该是getView调用5次且convertView全副为null,而事实上getView多调用了10次且有一次convertView为null。 同样的,咱们测试一下当layout\_height=”match\_parent”的状况: 另外,ListView内容超过一屏幕的状况下(思考复用机制),测试后果一样,这里就不再演示了。 在理论我的项目中,Adapter的getView办法承载着大量的业务逻辑,在性能方面,除去创立视图的损耗,不正确的ListView应用形式导致的性能损耗大概是失常的3倍左右!那么到底是什么起因导致的呢?咱们上面来简略剖析下ListView源码。 2 ListView代码剖析在演示了layout\_height=”wrap\_content”导致性能问题的景象之后,咱们来从源码的角度剖析下,呈现这种适度调用问题的根本原因。(源码以API 29为例) 2.1 onMeasure首先,layout\_height=”wrap\_content”属性意味着ListView的高度须要由子View决定,即在onMeasure的时候,须要一一测量子View的高度,所以咱们先从其onMeasure办法动手。 wrap\_content对应的mode为MeasureSpec.AT\_MOST,所以很容易就能找测量子视图高度的代码measureHeightOfChildren,当然办法名也体现进去了,所以具体来看这个办法 外围代码如上,很显著,所有的子View实例都是由obtainView办法返回的,而后再调用具体measureScrapChild来具体测量子View的高度,失常状况下这里for循环的次数就等于所有子项的个数,不过非凡的是已测量的子View高度之和大于maxHeight就间接return出循环了。这种做法其实很好了解,ListView能显示的最大高度就是屏幕的高度,如果有1000个子项,后面10项曾经占满了一屏幕了,那前面的990项就没必要持续测量高度了,这样能够大大提高性能。 另外,当一个子View测量完了之后,会通过recycleBin加到复用缓存之中,毕竟这个View只是测量了,还没有加到视图树之中,齐全是能够持续复用的。 持续来看obtainView办法的实现,源码在AbsListView中。 obtainView办法外面外围的代码其实就两行,首先从复用缓存中取出一个能够复用的View,而后作为参传入getView中,也就是convertView。 这时咱们梳理一下measure过程中调用getView的全过程: A、测量第0项的时候,convertView必定是null的,通常须要咱们Inflate一个View返回; B、第0项测量完结,这个第0项的View就被退出到复用缓存当中了; C、开始测量第1项,这时因为是有第0项的View缓存的,所以getView的参数convertView就是这个第0项的View缓存,而后反复B步骤增加到缓存,只不过这个View缓存还是第0项的View; D、持续测量3、4、5…项,反复C。 所以,咱们log中的状况是position=0,convertView=null,而position 1,2 … convertView都是同一个对象实例,即被复用第0项。 2.2 Layout当Measure过程完结了,上面就要开始Layout过程了,因为onLayout办法代码较多,咱们间接pass,来看makeAndAddView办法,也就是真真创立View的代码。 同样的,子View实例都是由obtainView办法返回的。这时候就有个小细节了,因为后面Measure的时候,第0项的View曾经创立了并且退出到了复用缓存当中,这一次就能够间接拿进去持续用了。接着创立第1,2 … 前面项的时候就没复用缓存了,只能一次次地Inflate。 所以,咱们log中的状况是position=0,convertView复用第0项,而position 1,2 … convertView=null。 按理说,Layout之后,应该就不会在调用getView办法了,然而咱们显著能看到log依然多了5次调用,那么这又是怎么回事呢? 后面说到onMeasure办法会导致getView调用,而一个View的onMeasure办法调用机会并不是由本身决定,而是由其父视图来决定。 ListView放在FrameLayout和RelativeLayout中其onMeasure办法的调用次数是齐全不同的。 2.3 小结因为onMeasure办法会屡次被调用,例子中是两次,其实残缺的调用程序是onMeasure - onLayout - onMeasure - onLayout - onDraw。所以咱们又会看到5次调用,和最后面5次是截然不同的。 那么,必定有童鞋又要问,既然onLayout也被执行两次,那为何不是调用5x2+5x2=20次呢? 在第2次onLayout的时候,因为数据并没有变动,即mDataChanged=false,这时候能够间接用以后项曾经存在的View了,不要再通过getView办法从新绑定数据,所以getView是不须要被调用的。 从下面的剖析中,咱们能够失去wrap\_content状况下getView被调用的机会和次数,假如onMeasure(heightMeasureSpec为AT\_MOST)次数为n,onLayout次数为m,ListView控件内同时显示的子项数为i,那么getView次数=(n + 1)\_i,失常状况match\_parent时,getView次数= i,多余的getView调用次数应该是 (n + 1)_i - i = n * i; 由公式能够看出getView多余调用次数与onMeasure次数n以及显示子项数i成正比关系。 ...

March 22, 2023 · 2 min · jiezi

关于android:刷爆-LeetCode-双周赛-100单方面宣布第一题最难

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。大家好,我是小彭。 上周末是 LeetCode 第 100 场双周赛,你加入了吗?这场周赛整体没有 Hard 题,然而也没有 Easy 题。第一题国服前百名里超过一半人 wa,很少见。 小彭的技术交换群 02 群来了,公众号回复 “加群” 退出咱们~ 周赛概览2591. 将钱分给最多的儿童(Easy) 题解一:模仿 $O(1)$题解二:齐全背包 $O(children·money^2)$2592. 最大化数组的平凡值(Medium) 题解一:贪婪 / 田忌赛马 $O(nlgn)$题解二:最大反复计数 $O(n)$2593. 标记所有元素后数组的分数(Medium) 题解一:排序 O$(nlgn)$题解二:依照严格递加字段分组 $O(n)$2594. 修车的起码工夫(Medium) 题解一:二分查找 $O(n + U·log(mc^2))$题解二:二分查找 + 计数优化 $O(n·log(mc^2))$2591. 将钱分给最多的儿童(Easy)题目地址https://leetcode.cn/problems/distribute-money-to-maximum-chil... 题目形容给你一个整数 money ,示意你总共有的钱数(单位为美元)和另一个整数 children ,示意你要将钱调配给多少个儿童。 你须要依照如下规定调配: 所有的钱都必须被调配。每个儿童至多取得 1 美元。没有人取得 4 美元。请你依照上述规定调配金钱,并返回 最多 有多少个儿童取得 恰好 **8 美元。如果没有任何调配计划,返回 -1 。 题解一(模仿)这道题搞数字科学?发发发 888? 简略模拟题,然而错误率很高,提交通过率仅 19%。 class Solution { fun distMoney(money: Int, children: Int): Int { var left = money // 每人至多调配 1 元 left -= children // 违反规定 2 if (left < 0) return -1 // 1、完满:正好所有人能够调配 8 元 if (left == children * 7) return children // 2、溢出:所有人能够调配 8 元有结余,须要抉择 1 集体调配结余的金额 if (left > children * 7) return children - 1 // 3、有余:尽可能调配 8 元 var sum = left / 7 // 结余金额 left -= sum * 7 // 如果结余 3 元,并且剩下 1 人调配了 1 元,须要毁坏一个 8 元避免出现调配 4 美元 if (left == 3 && children - sum == 1) return sum - 1 return sum }}复杂度剖析: ...

March 21, 2023 · 6 min · jiezi

关于android:不一样的-Android-堆栈抓取方案

图片来自:https://unsplash.com 本文作者: zy背景曾几何时,咱们只须要简简单单的一行 Thread.currentThread().getStackTrace() 代码就能够轻轻松松的获取到以后线程的堆栈信息,从而剖析各种问题。随着需要的一直迭代,APP 遇到的问题越来越多,卡顿,ANR,异样等等问题接踵而来,那么简简单单某个时刻的堆栈信息曾经不能满足咱们的需要了,咱们的眼光逐步转移到了每个时刻的堆栈上,如果能获取一个时间段内,每个时刻的堆栈信息,那么卡顿,以及 ANR 的问题也将被解决。 抓栈计划目前对于一段时间内的抓栈计划有两种: 办法插桩抓栈Native 抓栈代码插桩抓栈基本思路APP 编译阶段,对每个办法进行插桩,在插桩的同时,填入以后办法 ID,产生卡顿或者异样的时候,将之前收集到的办法 ID 进行聚合输入。 插桩流程图: 长处:简略高效,无兼容性问题 毛病:插桩导致所有类都非 preverify,同时 verify 与 optimize 操作会在加载类时被触发。减少类加载的压力照成肯定的性能损耗。另外也会导致包体积变大,影响代码 Debug 以及代码解体异样后谬误行数 Native 抓栈应用 Native 抓栈之前,咱们先理解一下 Java 抓栈的整个流程 JAVA堆栈获取流程图抓栈以后线程 抓栈其余线程 Java堆栈获取原理剖析因为以后线程抓栈和其余线程抓栈流程相似,这里咱们从其余线程抓栈的流程进行剖析首先从入口代码登程,Java 层通过 Thread.currentThread().getStackTrace() 开始获取以后堆栈数据 Thread.javapublic StackTraceElement[] getStackTrace() { StackTraceElement ste[] = VMStack.getThreadStackTrace(this); return str!=null?ste:EmptyArray.STACK_TRACE_ELEMENT; }Thread 中的 getStackTrace 只是一个空壳,底层的实现是通过 native 来获取的,持续往下走,通过 VMStack 来获取咱们须要的线程堆栈数据 dalvik_system_vmstack.ccstatic jobjectArray VMStack_getThreadStackTrace(JNIEnv* env, jclass, jobject javaThread) { ScopedFastNativeObjectAccess soa(env); // fn 办法是线程挂起回调 auto fn = [](Thread* thread, const ScopedFastNativeObjectAccess& soaa) REQUIRES_SHARED(Locks::mutator_lock_) -> jobject { return thread->CreateInternalStackTrace(soaa); }; // 获取堆栈 jobject trace = GetThreadStack(soa, javaThread, fn); if (trace == nullptr) { return nullptr; } // trace 是一个蕴含 method 的数组,有这个数据之后,咱们进行数据反解,就能获取到办法堆栈明文 return Thread::InternalStackTraceToStackTraceElementArray(soa, trace); }上述代码中,须要留神三个元素 ...

March 21, 2023 · 4 min · jiezi

关于android:一名七年老安卓的一二月小结

你好,我是 shixin,一名工作七年的安卓开发。 每两个月我会做一次总结,记下这段时间里有意义的事和值得重复看的内容,为的是留一些回顾、评估本人的行为、积淀有价值的信息。 一转眼 2023 年过来了六分之一,这两个月经验了不少事,趁着周末有工夫,细细推敲一下这段时光的得与失,以更好的姿势迎接下个双月。 历史总结: # 2022|一二# 2022|三四# 2022|五六# 2022|七八# 2022|九十# 2022 总结有什么有意义的事年度总结失去了认可 去年的年度总结失去了一个奖品,送给了老丈人,开心。 面试他人的同时反思本人一月份面试较多,从更高级别面试官的评估中学到了一些致力方向。 这些面试里我负责一面,次要关注根底、我的项目经验、资格匹配度和靠谱水平;二面是某部门负责人,次要关注音视频教训、技术广度、我的项目兼顾能力、带团队能力、工作稳定性。 二面面试官喜爱让面试者做「劣势自评和毛病自评」,这个问题挺好的,也让我开始思考本人的劣势、毛病: 劣势自评:有技术好奇心,有主动性,有强烈的进取心,技术广度和深度匹配工作年限<!----> 毛病自评:音视频经验不足,带团队能力缺乏经验印象粗浅的是一个工作 11 年的人,履历还是挺难看的,迅雷、百度、XX,但技术深度总感觉和年限不匹配,做的货色还是有点简略,模板化组件化、CodeReview、CICD...  聊完当前我不禁在想,是不是我的规范有问题?可能并不是所有人都有我遇到过那些大佬那么牛逼,做安卓下层业务的复杂度或者就是这些。 面试很多人后,我的感悟是一方面要调整本人的规范,另一方面也要致力成为更稀缺的人。 什么样的人算是稀缺的? 懂 ART 和 Linux 底层,有 NDK 开发教训<!----> 在性能优化/音视频/图像处理某个畛域有比拟深的实际<!----> 有带团队的教训<!----> 懂得前后端排查一个数据问题,思考如何做的更好一月份排查一个线上曝光数据问题,折腾了好几个版本,最初发现不是我的代码问题,明天反思一下如何做的更好。 问题背景: 十二月做了一个需要,上线后产品反馈埋点数据异样,曝光数据比预期少了很多<!----> 因为这个需要面向用户比拟细分,须要命中客户端和服务端的多个条件才会执行(先满足客户端条件才会调用服务端接口),所以排查到底是哪个环节出了花了良久(两个版本迭代的工夫)问题起因: 很久之前就存在的退出埋点,没有辨别具体退出行为,导致产品冀望的「指标用户数」偏多(误导我认为客户端条件判断有问题,导致没调用接口)<!----> 服务端权利发放接口有问题,导致指标用户没获取到权利(要害起因)如何解决的: 新增埋点,细分退出类型,以圈出真正的指标用户人群<!----> 减少接口返回值上报,以查看服务端返回信息<!----> 最初发现是服务端返回未获取到权利,进一步排查是权利发放接口有问题,没有发放给指标用户如何防止这种状况再产生? 如果退出埋点能够辨别退出类型,就不会有指标人群过大的问题,预期的曝光量就会少,剖析问题时也不会跑偏 当前做数据埋点时,要从技术角度多思考一下,看看目前的埋点属性是否够穷举所有可能,不够的话被动提出减少属性,以便前期剖析问题<!----> 如果一开始就上报一下有没有调用接口,而不是服务端说什么信什么,就能够早一点确定到底哪一步有问题 长链路要在要害节点(开关、接口、数据后果)减少埋点,配合开关,有问题时开启上报(debug 时强制开启)如果一开始多找后端确认下他那边权利下发成功率,可能也就不须要绕这么大弯路<!----> 剖析问题时要看的到整个链路,有质疑其余端的勇气,拉着后端一起排查,而不是本人一个人尝试小结:因为客户端间隔用户更近,出了问题常常会被认为是客户端的问题,后果排查半天发现不是本人问题的状况。咱们能做的就是:简单链路减少具体埋点,以备不时之需;理解需要的整个链路,遇到问题从整体思考哪里可能有问题,尽早拉别的端并行查看,提高效率。 团队奉献:积淀了两篇文章往年须要在「团队奉献」上多做一些致力,这两个月分享了两个工具,能够帮忙晋升开发效率。 从游戏排位中反思过程和后果随着年纪减少,能获取到乐趣的事件越来越少。当初休息日,娱乐我的项目根本就是刷短视频、打游戏,连电影都好久没看了。 一月份 lol 手游终于上了「巨匠」,为了上这个级别花了好几个早晨,两头一度连跪 6 把,心态崩了。 原本娱乐的目标是放松,是为了玩的过程中取得乐趣,但随着排位等级晋升,我的注意力根本全放到了「降级」上,每把的目标就是赢,有时候想选点感兴趣但不相熟的英雄,也因为放心输放弃了。 带来的后果就是,如果赢了情绪很好,但一旦本人被打爆或者遇到很坑的队友,就感觉这把完蛋白玩了。人不知;鬼不觉中,就遗记了娱乐的意义。 在某一瞬间,我感觉这种时候的我和「在追寻答案的悉达多」有些类似。那一刻的我心里齐全只有目标,看不到其余乏味的局部,感官因为心态变得灵通、心态因为后果变得焦躁,陷入了「只看后果的执念」。 尽管「活在当下」听人说了一万次,但我发现自己还是做不到,还是看重后果甚于过程。这点要改。 拍了个证件照一月份花一百块照了张形象照,跟照相师强调“要那种自信轻松的感觉”,拍进去的后果还算称心: 为什么要拍形象照呢? 次要是受前段时间看到的一个独立开发者网站,他的形象照很阳光自信,让人感觉值得信赖。 ...

March 19, 2023 · 2 min · jiezi

关于android:Kotlin-学习笔记二-数据类密闭类循环写法以及常用集合操作符

在上篇笔记中,咱们对 Kotlin 的根本类型、关键字、类与对象,以及与 Java 之间互调的内容有了一些意识,这篇笔记来看看 Kotlin 中几种非凡的类,以及汇合相干的罕用操作。 1. Kotlin 数据类Kotlin 语言中有个非凡的类叫 数据类,这个类型是 Kotlin 专门用来示意一个 Java Bean 的,为啥这么说?因为它帮咱们主动生成了一个数据类应该有的办法。比方:getter/setter 办法、toString()、hashCode()、equals()、copy() 办法。举个栗子: // code 1data class Book(val id: Int, val name: String) {}Kotlin 代码就这么点,而后再看看为咱们生成的 Java 代码:(如何查看生成的 Java 代码?找到 AndroidStudio 的 Tools 选项,顺次选 Kotlin、show Kotlin ByteCode,而后在新呈现的代码窗口点击 Decompile 就能够看到生成的 Java 代码了) // code 2public final class Book { private final int id; @NotNull private final String name; public final int getId() { return this.id; } @NotNull public final String getName() { return this.name; } public Book(int id, @NotNull String name) { Intrinsics.checkNotNullParameter(name, "name"); super(); this.id = id; this.name = name; } public final int component1() { return this.id; } @NotNull public final String component2() { return this.name; } @NotNull public final Book copy(int id, @NotNull String name) { Intrinsics.checkNotNullParameter(name, "name"); return new Book(id, name); } // $FF: synthetic method public static Book copy$default(Book var0, int var1, String var2, int var3, Object var4) { if ((var3 & 1) != 0) { var1 = var0.id; } if ((var3 & 2) != 0) { var2 = var0.name; } return var0.copy(var1, var2); } @NotNull public String toString() { return "Book(id=" + this.id + ", name=" + this.name + ")"; } public int hashCode() { int var10000 = this.id * 31; String var10001 = this.name; return var10000 + (var10001 != null ? var10001.hashCode() : 0); } public boolean equals(@Nullable Object var1) { if (this != var1) { if (var1 instanceof Book) { Book var2 = (Book)var1; if (this.id == var2.id && Intrinsics.areEqual(this.name, var2.name)) { return true; } } return false; } else { return true; } }}想不到吧?一行 Kotlin 居然帮咱们干了这么多事!这也阐明用 Kotlin 的确能缩小代码量,晋升 Coding 效率。再看看 Kotlin 数据类的特点。 ...

March 18, 2023 · 6 min · jiezi

关于android:如何让虚拟角色自然融入现实

随着AR的倒退,虚构角色被广泛应用在游戏、直播、社交等App中。例如在直播App里,商家能够自在打造虚构主播的形象,通过AR算法能够让虚构形象在介绍时做到不遮挡实物商品,晋升直播真实性和趣味性。那么,如何让虚构角色天然融入事实,实现与用户的实在交互呢? 华为HMS Core AR Engine提供单人或双人身材轮廓的辨认和跟踪能力,实时输入人体轮廓Mask信息和对应的骨骼点信息。其中人体Mask能力能够辨认和跟踪以后画面人体所在区域,反对多人辨认,识别率达90%,并提供该区域的深度信息。 通过人体轮廓跟踪能力,开发者们可利用人体的轮廓Mask信息对虚构物体和场景进行遮蔽。比方在AR拍照时更换虚构背景、让虚构玩偶躲到人身后等,都可应用Mask能力来实现更为天然的遮挡成果,这可进一步晋升AR利用的真实感和观看体验。 Demo演示 开发步骤开发筹备1 .注册成为开发者在开发利用前须要在华为开发者联盟网站上注册成为开发者并实现实名认证,具体方法请参见帐号注册认证。 2 .创立利用参见创立我的项目和在我的项目下创立利用实现利用的创立,配置如下: “抉择平台”:抉择“Android”。 “反对设施”:抉择“手机”。 “利用分类”:抉择“利用”或“游戏”。 3 .集成AR Engine SDK华为提供了Maven仓集成形式的AR Engine SDK包,在开始开发前,须要将AR Engine SDK集成到您的开发环境中。 4 .配置AR Engine SDK的Maven仓地址Android Studio的代码库配置在Gradle插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请依据您以后的Gradle插件版本,抉择对应的配置过程。 5 .增加编译依赖关上我的项目中利用级的“build.gradle”文件。 在“dependencies”中增加如下编译依赖。dependencies { implementation 'com.huawei.hms:arenginesdk:{version}'}从新关上批改完的build.gradle文件,右上方呈现Sync Now链接。点击“Sync Now”期待同步实现。利用开发运行前验证 查看以后设施是否装置了AR Engine,若曾经装置则失常运行,若没有装置,App应采纳适合的形式揭示用户装置AR Engine,如被动跳转利用市场,申请装置AR Engine。具体实现代码如下(具体请参见示例代码)。 boolean isInstallArEngineApk = AREnginesApk.isAREngineApkReady(this);if (!isInstallArEngineApk) { // ConnectAppMarketActivity.class为跳转利用市场的Activity。 startActivity(new Intent(this, com.huawei.arengine.demos.common.ConnectAppMarketActivity.class)); isRemindInstall = true;}创立BodyActivity用来展现AR Engine辨认能力,展现身材骨骼,输入人体特色。Public class BodyActivity extends BaseActivity{Private BodyRendererManager mBodyRendererManager;Protected void onCreate(){ //初始化surfaceView mSurfaceView = findViewById(); //放弃OpenGL ES运行上下文。 mSurfaceView.setPreserveEGLContextOnPause(true); //设置OpenGLES版本。 mSurfaceView.setEGLContextClientVersion(2); //设置EGL配置选择器,包含色彩缓冲区的位数和深度位数。 mSurfaceView.setEGLConfigChooser(……); mBodyRendererManager = new BodyRendererManager(this); mSurfaceView.setRenderer(mBodyRendererManager);mSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); }Protected void onResume(){ //初始化ARSession,用于治理AR Engine的整个运行状态If(mArSession == null){mArSession = new ARSession(this.getApplicationContext());mArConfigBase = new ARBodyTrackingConfig(mArSession);mArConfigBase.setEnableItem(ARConfigBase.ENABLE_DEPTH | ARConfigBase.ENABLE_MASK);mArConfigBase.setFocusMode(ARConfigBase.FocusMode.AUTO_FOCUSmArSession.configure(mArConfigBase); } //给setBodyMask传入须要的参数mBodyRendererManager.setBodyMask(((mArConfigBase.getEnableItem() & ARConfigBase.ENABLE_MASK) != 0) && mIsBodyMaskEnable);sessionResume(mBodyRendererManager); }}创立BodyRendererManager, 此类渲染AR Engine获取的集体数据。Public class BodyRendererManager extends BaseRendererManager{ Public void drawFrame(){ //获取所有指定类型的可跟踪对像汇合Collection<ARBody> bodies = mSession.getAllTrackables(ARBody.class); for (ARBody body : bodies) {if (body.getTrackingState() != ARTrackable.TrackingState.TRACKING){ continue; }mBody = body;hasBodyTracking = true; } //更新屏幕上显示的身材辨认信息。StringBuilder sb = new StringBuilder(); updateMessageData(sb, mBody);Size textureSize = mSession.getCameraConfig().getTextureDimensions();if (mIsWithMaskData && hasBodyTracking && mBackgroundDisplay instanceof BodyMaskDisplay) { ((BodyMaskDisplay) mBackgroundDisplay).onDrawFrame(mArFrame, mBody.getMaskConfidence(), textureSize.getWidth(), textureSize.getHeight()); } //在屏幕上显示更新后的身材信息。mTextDisplay.onDrawFrame(sb.toString());for (BodyRelatedDisplay bodyRelatedDisplay : mBodyRelatedDisplays) { bodyRelatedDisplay.onDrawFrame(bodies, mProjectionMatrix); } catch (ArDemoRuntimeException e) { LogUtil.error(TAG, "Exception on the ArDemoRuntimeException!"); } catch (ARFatalException | IllegalArgumentException | ARDeadlineExceededException | ARUnavailableServiceApkTooOldException t) { Log(…); }}//更新手势相干数据以进行显示。Private void updateMessageData(){ if (body == null) { return; } float fpsResult = doFpsCalculate(); sb.append("FPS=").append(fpsResult).append(System.lineSeparator()); int bodyAction = body.getBodyAction();sb.append("bodyAction=").append(bodyAction).append(System.lineSeparator());}}自定义相机预览类,用于实现基于肯定置信度的人体绘制。Public class BodyMaskDisplay implements BaseBackGroundDisplay{}获取骨架数据并将其传递给OpenGL ES,OpenGL ES将渲染数据并在屏幕上显示。public class BodySkeletonDisplay implements BodyRelatedDisplay {获取骨架点连贯数据,并将其传递给OpenGL ES以便在屏幕上渲染。public class BodySkeletonLineDisplay implements BodyRelatedDisplay {}其余类内容请参考示例代码集成。 ...

March 16, 2023 · 2 min · jiezi

关于android:应用内支付服务现网沙盒环境下常见关键事件的对比与总结

在集成和调试订阅型商品时,咱们会依赖沙盒环境来进行模仿理论场景。 订阅型商品的购买流程和一次性商品的购买流程相似,但订阅还有其余细节场景,比方续订胜利或失败,续订周期时长等。沙盒环境下的订阅续订工夫会比失常状况更快,引入“时光机”概念帮忙您疾速测试您利用的订阅场景。比方订阅周期为1周,商品在3分钟后产生续期,此时订阅型商品有效期缩短了3分钟。 上面对沙盒环境和现网环境订阅告诉事件进行简略比照,针对两种环境下收到的notificationType事件进行对照。 a) 撤销订阅 测试一:购买商品后,在主动续费前撤销订阅: 测试二:购买商品后,商品到期并产生主动续期后再撤销原订阅: 总结:沙盒环境、现网环境对于撤销订阅后,订阅商品都立刻隐没,同时这笔订阅费都用会立即发动返还,后续不再主动续期。订阅告诉事件上,因为沙盒环境采纳了时光机概念,短期内会屡次收到续期胜利的订阅事件告诉。 b) 设置暂停打算 场景剖析 正式环境下: 7月28号14:27首次购买周卡,返回订阅要害事件0。0示意首次购买。 7月28号14:28勾销订阅,返回订阅要害事件5。5示意订阅进行。 7月28号14:29复原订阅,返回订阅要害事件6,复原订阅。 7月28号14:29设置暂停打算一周,返回订阅要害事件11,11示意设置了暂停续期打算(包含暂停打算的创立、批改以及在暂停打算失效前的打算终止)。 8月5号13:27进入暂停期,原订阅是7月28号购买的周卡,到期工夫是8月4号,8月5号进入暂停期,收到告诉10。 8月8号09:17复原续订,此时商品已到期,收到要害事件告诉3、6。3示意复原一个已过期的订阅,6示意续期恢复正常。 沙盒环境下: 9月20号10:17首次购买半年卡,返回订阅要害事件0。0示意首次购买,与正式环境统一。 9月20号10:18勾销订阅,返回订阅要害事件5。与正式环境统一。 9月20号10:19复原订阅,返回订阅告诉6和7,与正式环境多返回告诉7,这个沙盒设置如此,正式环境不受影响。 9月20号10:19设置暂停25分钟,返回订阅告诉11(示意创立、暂停打算失效前终止)。商品11:17分到期后进入暂停期25分钟。 沙盒下进入暂停期没有收到要害事件告诉10。是因为暂停和过期事件是通过预先查看发现的,目前是通过每日查看发现订阅进入暂停期或是过期。因为沙盒周期短,在次日查看时周期曾经完结,所以没有10的事件告诉,正式环境下失常。 9月20号11:25在暂停期内,手动复原续订,返回订阅告诉3和6,与正式环境统一。 之后每隔半小时主动续订一次。 理解更多详情>> 拜访华为开发者联盟官网 获取开发领导文档 华为挪动服务开源仓库地址:GitHub、Gitee 关注咱们,第一工夫理解 HMS Core 最新技术资讯~

March 15, 2023 · 1 min · jiezi

关于android:巧用预测多触点促业务可持续增长

信息化时代,内部市场环境一直变动,企业数字化营销转型过程放慢。数据孤岛的突破以及细颗粒级的用户精细化经营帮忙越来越多的开发者实现业务增长。 本文咱们将介绍如何以华为剖析服务的预测能力为前提,结合实际场景,通过Push、利用内音讯、近程配置等多样化的用户触达形式,多触点经营促成业务的可持续增长。 场景一:预测人群情景化触达,晋升经营效率家喻户晓,防患未然比亡羊补牢更加高效。同样,在用户经营过程中,通过AI算法提前预测用户在近期一段时间内产生某要害行为的概率,如散失、付费等。以用户潜在志愿为参考制订经营策略,将无效晋升经营效率。 举个例子,通过付费预测模型可从近7天的沉闷用户中圈定将来一周内高概率付费人群,那么,当这部分用户浏览App内的某些要害页面时,比方会员介绍页、道具展现页等,就能够借助利用内音讯,以浏览该页面作为触发事件,对高概率付费人群推送如“限时折扣套餐”这样的弹窗音讯。基于用户原有付费志愿,联合失当机会的情景化触达,可无效缩小用户在付费过程中的心理博弈,促成付费转化。 图示为针对高概率付费用户创立利用内音讯 场景二:预测人群差异化经营,开掘增长动能当产品进入稳定增长阶段,千人一面的传统经营形式显然难以留住用户,更别提从用户身上开掘增长付费点。上文提到,预测能够让咱们提前理解用户的行为志愿,那么,通过差异化的人群经营,则有利于开掘更多增长动能。 某休闲益智类手游,以利用内购买和游戏内广告支出为次要盈利形式。随着市场上同类产品的不断涌现,如何正当地在玩家游戏体验和广告点击增加收入两者间寻找平衡点,成了其日常经营的一大难点。 付费预测模型将最近一周的沉闷用户划分为不同概率的付费群体,经营人员依据用户付费概率的高下,联合近程配置性能对用户闯关失败后的界面做了差异化展现。高概率的付费用户配置复活道具举荐界面,而低概率付费用户则配置广告激励视频。既不影响潜在付费大R用户的游戏体验,又能够肯定水平上减少利用内的广告点击。 图示为针对高概率付费用户增加近程配置条件 场景三:预测人群多样化剖析,摸索用户行为差别根因用户从沉闷到散失,历经一个十分要害的缄默期,只有把握住这个阶段,深度剖析其共性行为特色与属性偏好,找到相干症结点,能力隔靴搔痒。 某社交类利用,通过散失预测模型提前圈定了不同概率将在将来一周内散失的用户,在查看高概率散失用户的利用版本散布时,发现简直都集中在了新版本。 图示为某利用高概率散失用户版本散布详情 推断剖析:用户虽更新版本但却易散失,很有可能是因为新版本玩法的不理解。可通过适当地音讯推送,对预测的高概率散失用户针对性推送新版本玩法介绍等音讯,以促成用户再次沉闷。 当然,也能够联合用户分群,通过更深层次的用户行为剖析,摸索高风险散失用户的根因。例如,上述高概率散失用户集中在新版本,能够依据用户属性,将应用新版本的用户创立一个细分受众。创立实现后,再通过受众组合的形式,将预测的高概率散失用户与应用新版本的用户取交加,这样就能够圈定出应用新版本的高概率散失用户。 图示为通过华为剖析创立组合受众界面 创立实现的受众可在“过滤器”中作为筛选条件,联合其余剖析报告剖析这部分用户的行为特色。例如,能够在页面路径分析报告中,通过过滤器筛选该受众,查看其行为门路特色;同样可在启动剖析报告中查看该受众的启动时段散布等。以进一步公开钻,深度洞察用户趋于散失的利用内行为偏好。 以上就是华为剖析服务预测能力针对用户分层精细化经营的简略介绍,置信通过情景化、差异化、多样化等不同的经营触达形式,将显著进步您的经营工作效率。 理解更多详情>> 拜访华为开发者联盟官网 获取开发领导文档 华为挪动服务开源仓库地址:GitHub、Gitee 关注咱们,第一工夫理解 HMS Core 最新技术资讯~

March 13, 2023 · 1 min · jiezi

关于android:LeetCode-周赛-336多少人直接-CV

大家好,我是小彭。 明天早上是 LeetCode 第 336 场周赛,你加入了吗?这场周赛整体品质比拟高,然而最初一题是老题,CV 能过。然而输出数据范畴被升高了,这操作也是没谁了。 2587. 统计范畴内的元音字符串数(Easy)题目地址https://leetcode.cn/problems/count-the-number-of-vowel-string... 题目形容给你一个下标从 0 开始的字符串数组 words 和两个整数:left 和 right 。 如果字符串以元音字母结尾并以元音字母结尾,那么该字符串就是一个 元音字符串 ,其中元音字母是 'a'、'e'、'i'、'o'、'u' 。 返回 words[i] 是元音字符串的数目,其中 i 在闭区间 [left, right] 内。 题解(模仿)简略模拟题。 class Solution { fun vowelStrings(words: Array<String>, left: Int, right: Int): Int { val set = hashSetOf('a', 'e', 'i', 'o', 'u') var count = 0 for (index in left..right) { val word = words[index] if (set.contains(word[0]) && set.contains(word[word.length - 1])) count++ } return count }}复杂度剖析: 工夫复杂度:$O(n)$空间复杂度:$O(1)$2588. 重排数组以失去最大前缀分数(Medium)题目地址https://leetcode.cn/problems/rearrange-array-to-maximize-pref... 题目形容给你一个下标从 0 开始的整数数组 nums 。你能够将 nums 中的元素按 任意程序 重排(包含给定程序)。 令 prefix 为一个数组,它蕴含了 nums 重新排列后的前缀和。换句话说,prefix[i] 是 nums 重新排列后下标从 0 到 i 的元素之和。nums 的 分数 是 prefix 数组中正整数的个数。 返回能够失去的最大分数。 题解(贪婪)贪婪思路:正数会升高前缀和,为了延缓前缀和变小的速度,正权值应该放在尽可能前的地位,负权值放在尽可能后的地位,即对数组降序排序。 class Solution { fun maxScore(nums: IntArray): Int { // 3 2 1 0 -1 -3 -3 // 3 5 6 6 5 2 -1 nums.sortDescending() var preSum = 0L for (index in nums.indices) { preSum += nums[index] if (preSum <= 0L) return index } return nums.size }}复杂度剖析: ...

March 12, 2023 · 6 min · jiezi

关于android:浅谈Android主题样式

浅谈Android主题款式文章开端有附带例子的源码链接, 感兴趣的能够下载源码钻研, 滋味更佳.在讲Android主题之前, 让咱们先回顾一下Android中自定义View的实现办法. 自定义View齐全自定义View实现自定义控件自定义View、ViewGroup或者SurfaceView: 自定义View:次要重写onDraw(绘制)办法。自定义View实现例子自定义ViewGroup:次要重写:onMeasure(测量)、onLayout(布局)这两个办法。自定义ViewGroup实现例子自定义SurfaceView:创立RenderThread,而后调用SurfaceHolder的.lockCanvas办法获取画布,再调用SurfaceHolder的.unlockCanvasAndPost办法将绘制的画布投射到屏幕上。class CustomSurfaceView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null,) : SurfaceView(context, attrs), SurfaceHolder.Callback { private var mSurfaceHolder: SurfaceHolder = holder private lateinit var mRenderThread: RenderThread private var mIsDrawing = false override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {} override fun surfaceCreated(holder: SurfaceHolder) { // 开启RenderThread mIsDrawing = true mRenderThread = RenderThread() mRenderThread.start() } override fun surfaceDestroyed(holder: SurfaceHolder) { // 销毁RenderThread mIsDrawing = false mRenderThread.interrupt() } /** * 绘制界面的线程 */ private inner class RenderThread : Thread() { override fun run() { // 不停绘制界面 while (mIsDrawing) { drawUI() try { sleep(...) // 刷新距离 } catch (_: InterruptedException) { } } } } /** * 界面绘制 */ private fun drawUI() { val canvas = mSurfaceHolder.lockCanvas() try { drawCanvas(canvas) } catch (e: Exception) { e.printStackTrace() } finally { mSurfaceHolder.unlockCanvasAndPost(canvas) } }}自定义SurfaceView实现例子 ...

March 11, 2023 · 2 min · jiezi

关于android:JetpackCompose-学习笔记一-Compose-初探

历时两年,Android 团队推出了全新的原生 Android 界面 UI 库——Compose。当然,Compose 也是属于 Jetpack 工具库中的一部分,官网声称能够简化并放慢 Android 上的界面开发,能够用更少的代码去疾速打造活泼而精彩的利用。1.0 版本就在上个月底刚刚公布,而且能够在生产环境中应用!不论咋样,先上手看一看! 1. 上手老本如何?个人感觉,还行,有肯定的学习老本。前提条件,对 Kotlin 语言相熟,因为 Compose 都是用 Kotlin 语言开发实现的,对其余的 Jetpack 库相熟就更好了。 Compose 能够和现有的工程项目进行互操作。比方,咱们能够将 Compose UI 放到现有布局的 View 中,也能够将 View 放到 Compose UI 中。 作为 Jetpack 工具库的一部分,Compose 当然也能够非常不便地与 LiveDada、ViewModel、Paging 等工具一起整合,从而进步编码效率。 Compose 也提供了 Material Design 组件和主题的实现,同时还有扼要的动画 API 能够让利用更加灵动,体验更好。 2. 官网广告概述Google 毕竟憋了两年,怎么说也得有两把刷子的。Compose 是 Google 新推出的实用于 Android 的旧式申明性界面工具包。集体了解的申明性的意思是:UI 的控件只须要咱们一开始的时候申明创立进去,绑定了数据就能够了,后续的更新能够全副交给 Compose 解决。 Google 是思考到当初的利用展现的绝大多数不是静态数据,更多的是会实时更新的。而现有的 xml 界面,更新比较复杂繁琐,很容易呈现同步谬误。并且软件维护的复杂性还会随着须要更新的视图数量而增长,为了解决这一问题,Google 才想齐全舍弃原有的用 xml 写视图的计划,从新开发出 Compose 这一整套的解决方案。 Compose 首先会生成整个屏幕,而后仅仅执行必要的更改。它是将 State 状态转化成 UI 界面,并且会智能地跳过那些数据没有产生扭转的控件,从新生成曾经产生扭转的控件,这一过程称之为重组(recomposition)。此外,Compose 布局模型不容许屡次测量,最多进行两次测量就可算出各组件的尺寸。 ...

March 11, 2023 · 5 min · jiezi

关于android:一个在手机浏览器上使用OneNote的方法可多设备同步

OneNote是大多数人都会用到的工具类软件,最罕用于笔记本电脑或台式电脑,但这套软件更适宜用于反对手写笔操作的平板电脑,在这类设施上可应用触笔、声音或视频创立笔记。 而咱们日常在应用浏览器的时候也须要记录一些货色,比方网页中的一些文章、图片、片段等,须要有一个记录的中央。但如果将这些网页都保留为书签的话,兴许之后查找起来还是不够直观。 这个时候就能够用到一个浏览器插件:OneNote Web Clipper。 这是一个电脑浏览器和手机浏览器都能够应用的插件,电脑端就不用说了,Chrome、Edge或者Firefox应该都能够。手机浏览器我用的是狐猴浏览器,因为平时应用手机更频繁和不便,所以这篇文章次要讲一下在手机上应用OneNote Web Clipper的办法。 装置步骤:关上狐猴浏览器的Edge扩大商店,如果你会迷信上网,Chrome也是能够的。 搜寻OneNote Web Clipper,下载。 次要性能:整页:剪切整个网页,将整个网页主动生成为一张长截图区域:裁剪某个区域并生成截图文章:自动识别文章书签:与浏览器书签性能相似裁剪好你须要的内容后,点击【剪辑】就能够将内容保留到OneNote中,插件也会弹出窗口提醒你到OneNote中查看。点击按钮就能够间接到网页版的OneNote中查看保留的内容了。 在应用OneNote Web Clipper插件之前会让你先登录Microsoft账号,之后保留的内容就能够同步到账号内,无论你是在电脑端应用程序、挪动端应用程序或是网页中都能看到你保留的内容,实现互联互通。 总的来说,这个插件功能完善,能够用在多个场景中,比方做游览攻略、学术研究、新闻收集等等。装置在手机浏览器中,即便是不不便关上电脑或平板的时候也能够疾速保留或者查看。

March 9, 2023 · 1 min · jiezi

关于android:Java-剑指offer29顺时针打印矩阵

题目输出一个矩阵,依照从内向里以顺时针的程序顺次打印出每一个数字。 思路每次打印矩阵最里面的一圈(用办法printMatrixInCircle()示意),每次都是这个操作,所以能够采纳递归。每次打印矩阵的左上角的横纵坐标雷同,即为start,而其余三个角的坐标都与行列数以及start无关,因而只须要for循环即可实现打印。 当然,其实只有针对start进行循环判断, start*2的值小于行数和列数时才须要持续打印,这样,通过这个条件,能够用循环来打印每次的最外圈矩阵。 测试算例 ** 多行多列,单行多列,多行单列,一个数的矩阵,空矩阵,null Java代码//题目:输出一个矩阵,依照从内向里以顺时针的程序顺次打印出每一个数字。public class PrintMatrix { public void printMatrix(int[][] matrix) { if(matrix==null || matrix.length<=0) return; printMatrixInCircle(matrix, 0); } private void printMatrixInCircle(int[][] matrix,int start) { int row=matrix.length; int col=matrix[0].length; int endX=col-1-start; int endY=row-1-start; if(endX<start || endY<start) return; //仅一行 if(endY==start) { for(int i=start;i<=endX;i++) { System.out.print(matrix[start][i]+" "); } return; //记得完结 } //仅一列 if(endX==start) { for(int i=start;i<=endY;i++) { System.out.print(matrix[i][start]+" "); } return; //记得完结 } //打印边界 for(int i=start;i<=endX;i++) { System.out.print(matrix[start][i]+" "); } for(int i=start+1;i<=endY;i++) { System.out.print(matrix[i][endX]+" "); } for(int i=endX-1;i>=start;i--) { System.out.print(matrix[endY][i]+" "); } for(int i=endY-1;i>=start+1;i--) { System.out.print(matrix[i][start]+" "); } //持续打印更外部的矩阵,令start+1 printMatrixInCircle(matrix, start+1); } public static void main(String[] args) { PrintMatrix demo = new PrintMatrix(); int[][] a= {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};// int[][] a= {};// int[][] a= {{}};// int[][] a= {{1}};// int[][] a= {{1,2,3,4}};// int[][] a= {{1},{2},{3},{4}};// int[][] a= {{1,2,3},{4,5,6}};// int[][] a=null; demo.printMatrix(a); }上面的代码是来牛客网:https://www.nowcoder.com/questionTerminal/9b4c81a02cd34f76be2...的C++代码:1.采纳的是循环;2.在打印一圈时,单行或者单列状况只须要在从右往左打印和从下往上打印时判断是否会呈现反复打印(即前面两个for循环)。代码比拟简洁。 ...

March 8, 2023 · 1 min · jiezi

关于android:如何防止-Android-应用被二次打包

以下是一些罕用的办法: 1.应用代码混同工具:代码混同能够使反编译后的代码难以浏览和了解,从而减少二次打包的难度。 在 Android 开发中,罕用的代码混同工具是 ProGuard。上面是在 Android Studio 中配置 ProGuard 的相干代码: 1) 在 app 的 build.gradle 文件中,增加以下代码: android { // 省略其余配置 buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }}2) 在我的项目根目录下创立 proguard-rules.pro 文件,用于指定混同规定。以下是一些罕用的规定: # 根本规定-optimizationpasses 5 # 优化次数-dontusemixedcaseclassnames # 不应用混合大小写的类名-dontskipnonpubliclibraryclasses # 不跳过非公共库的类-dontpreverify # 不预验证# 代码混同规定-keep class com.example.** {*;} # 保留 com.example 包及其子包中的所有类-keepclassmembers class com.example.** {*;} # 保留 com.example 包及其子包中的所有类成员-dontwarn com.example.** # 不正告 com.example 包及其子包中的类# 其余规定-keepattributes Signature-keepattributes *Annotation*以上代码只是一个简略示例,理论的混同规定须要依据具体的利用进行调整和优化。实现以上步骤后,在进行 release 版本打包时,ProGuard 会主动对代码进行混同和优化,从而减少利用的安全性。 ...

March 8, 2023 · 3 min · jiezi

关于android:2022-年度Android最不可赦漏洞

原文链接:https://mp.weixin.qq.com/s/P_EYQxOEupqdU0BJMRqWsw 一、背景最近,国内网络安全公众号“DarkNavy”昨日公布文章《2022 年度最“不可赦”破绽》称,有出名互联网厂商继续开掘新的安卓OEM零碎相干破绽,在其公开公布的 App 中实现对目前市场支流手机零碎的破绽攻打。(疑似PDD) 依据DarkNavy的表述,该互联网厂商应用了多种黑客伎俩,实现对用户手机的提权、隐衷信息收集、利用防卸载、利用长期驻留后盾等守法违规行为。  比方,该互联网厂商旗下App利用了多个安卓手机厂商 OEM 代码中的反序列化破绽,实现手机零碎提权。实现提权后,该 App 事实上曾经实现了反客为主,通过 App 管制了用户的整个手机零碎。 在提权管制手机零碎之后,该 App 即开启了一系列的违规操作,绕过隐衷合规监管,大肆收集用户的隐衷信息(包含社交媒体账户材料、地位信息、Wi-Fi 信息、基站信息甚至路由器信息等)。  之后,该 App 进一步应用其余黑客技术伎俩,冲破零碎沙箱机制、绕开权限零碎改写零碎要害配置文件为本身保活(注:放弃过程继续沉闷),批改用户桌面配置暗藏本身或坑骗用户实现防卸载,通过多种操作实现更加荫蔽的长期驻留,甚至还实现了和特务软件一样的“云控开关”遥控机制,来规避平安检测。 最终,该互联网厂商通过上述一系列荫蔽的黑客技术伎俩,在其非法 App 的背地,达到了荫蔽装置晋升装机量、非法晋升 DAU/MAU、用户无奈卸载、攻打竞争对手 App、窃取用户隐衷数据、回避隐衷合规监管等各种违规守法目标。  二、破绽剖析2022 年,Google 的 Project Zero 公布了一个在朝破绽利用的剖析,正告攻击者曾经瞄准各手机厂商的 OEM 代码局部,挖掘出其中的软弱点和破绽,组合出了一套残缺的提权攻打 Exploit。Project Zero 剖析的破绽利用链蕴含四个局部,齐全由三星代码中的破绽组成。 第一步,攻击者利用了 破绽 (CVE-2021-25337),这是一个 system_server 中导出的 semclipboardprovider 所存在的任意文件读写,容许攻击者以 untrusted_app 身份读写 users_system_data_file,也就是个别 system_app 的公有数据文件。  第二步,攻击者参考了三星 TTS 破绽研究成果,利用 TTS 中从本身配置文件加载任意动态链接库的能力,将第一个破绽转化为了一个 system_app 提权破绽。 在获取了 system_app 权限的代码执行能力后,攻击者执行最初两步,向内核进发: 首先,将三星设施中未更新的 Mali GPU 驱动内核信息泄露破绽 (CVE-2021-25369) ,和三星本人的 kmsg 泄露“个性”组合利用,最终取得内存基址和 addr_limit 地址。 ...

March 7, 2023 · 1 min · jiezi

关于android:一进群就水群试试这个水群拦截工具

大家好,我是小彭。 周末了,能够劳动了,来自习室劳动吧。最近交换群人数越来越多,群里的小伙伴还个个都是人才,谈话又好听,每天关上微信看都是满屏的 999+条新音讯~ 到起初有些长得帅的间接把咱们的群备注为 小彭的吹水群,给我气的。 水群是一门技术活,水得恰到好处能够让群处于一个非常沉闷的状态。然而水多了也不好,说多了没有技术性会让大家的取得感升高,那就没意思了。 此处引出水群状态转移过程: 太水了 -> 大佬懒得看 -> 技术问题不好解答 -> 技术性降落 -> 屏蔽了 -> 大佬懒得看 -> ... 为了进步交换群的技术气氛,去年咱们在群里发动过一次投票,最终的抉择的策略是分群: 技术群: 咱们心愿营造 work-life balance 的技术学习气氛,让气味相投,酷爱技术的小伙伴能够聚起来聊技术,聊生存,聊程序员的所有,但期待有所均衡。你也能够分享文章,发招聘广告,推广新书,推广流动。娱乐群: 你能够畅所欲言,自由发挥,能够聊生存,聊感情,聊你当初的情绪。例如团聚、玩乐、静止、读书、情感、事业、学业,找到气味相投的小伙伴。未来 2 群也能够采纳其余策略,听大伙的意见。 当初很多小伙伴会相互揭示,把水量疏导到吹水群里,你们太 nice 了~ 故事到这里就 告一段落了 快乐得太早了!不得不说我还是低估了你们的水量。我发现有些小伙伴开始是带着问题进群的,后果聊着聊着就遗记手头的事件了,整一个被带偏好吧。 我平时会应用滴答清单上的 番茄专一 性能,前几年我还会用滴答清单记笔记记想法,当初迁徙到 notion 后就还剩下番茄工夫性能在应用。番茄工夫工具有很多,捡手边趁手的就行。 最近,我发现滴答清单不仅可能本人专一(自闭),还能拉着一群人专一(个体自闭)—— 专一自习室。所以,我组建了一个 “Android 周末自习室” ,联合番茄专一性能,兴许成果会挺不错。效率工具,有用就用。 滴答清单的性能挺多的,简略说一下番茄专一性能怎么应用: 1、设置:先找到专一页,从右上角进入专一设置页,把严格模式拉满;设置到最严格模式 2、开始专一:回到专一页,翻转手机开始,如果你不喜爱这种形式,也能够从新设置到默认的点击开始形式。翻转手机 3、水群:想多了,提问题是能够的,水群是不可能的。只有你关上非白名单利用,滴答清单过几秒后就会喊你拉回去。水群拉回 别问,问就是悬浮窗权限~ 自习室还有榜单性能,挺好玩的: 就说这么多了,你试试看。周末了,没事来自习室看看: 彭旭锐 邀请你退出滴答清单自习室。房间号:rahgy5va,快来抢占「滴答清单自习室」学霸地位!关上“滴答清单”app — 专一性能“番茄专一设置” — “专一自习室”搜寻房间号,即可退出。https://api.dida365.com/sl/BPePYkRJRY之前在文章里贴群二维码图片会被广告脚本扫描,就不贴了,你能够间接在公众号里回复 加群 找我邀请你进群。咱们的群主旨:凋谢 - 纯正 - 脑洞 - 互助,欢送你来。 ...

March 6, 2023 · 1 min · jiezi

关于android:LeetCode-周赛-335纯纯手速场

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。大家好,我是小彭。 昨晚是 LeetCode 第 335 场周赛,你加入了吗?这场周赛整体难度不高,有两道模板题,第三题和第四题应该调换一下地位。 小彭的 Android 交换群 02 群来了,公众号回复 “加群” 退出咱们~ 2582. 递枕头(Easy)题目地址https://leetcode.cn/problems/pass-the-pillow/ 题目形容n 集体站成一排,按从 1 到 n 编号。 最后,排在队首的第一个人拿着一个枕头。每秒钟,拿着枕头的人会将枕头传递给队伍中的下一个人。一旦枕头达到队首或队尾,传递方向就会扭转,队伍会持续沿相同方向传递枕头。 例如,当枕头达到第 n 集体时,TA 会将枕头传递给第 n - 1 集体,而后传递给第 n - 2 集体,依此类推。给你两个正整数 n 和 time ,返回 t 题解一(模仿)简略模拟题。 class Solution { fun passThePillow(n: Int, time: Int): Int { var index = 1 var flag = true for (count in 0 until time) { if (flag) { if (++index == n) flag = !flag } else { if (--index == 1) flag = !flag } } return index }}复杂度剖析: ...

March 5, 2023 · 5 min · jiezi

关于android:Kotlin-学习笔记一

最近开始学习 Kotlin 语言了,打算搞个笔记系列,这是首篇~根本类型 var age: Int = 123 // 规范语法,申明一个可变变量 age val name: String = "Tom" // 规范语法,申明一个不可变变量 name (不可变变量不是常量) val sex: String? = null // 申明一个可为空的字符串变量 sex,String 与 String? 不是同种类型String 和 String? 是两种类型,前者润饰的变量不可为 null 空值;后者加了 “?” 之后润饰的变量就能够为 null 了,这也是 kotlin 空平安的一种体现。 当编译器能够推断出变量的数据类型时,能够不必写冒号和前面的数据类型,例如: var age = 123 // 可推断出 age 为 Int,所以可不写 val name = "Tom" // 可推断出 name 为 String,所以可不写双感叹号 “!!” 能够强转类型,如下代码。 name2 是可为空的 String? 类型,间接赋给不可为空的 name1 就会报错。如果确定 name2 肯定不为空,则能够在前面加上 "!!" 强转。 ...

March 5, 2023 · 4 min · jiezi

关于android:LeetCode-双周赛-99纯纯送分场

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。大家好,我是小彭。 昨晚是 LeetCode 第 99 场双周赛,你加入了吗?这场周赛整体难度很低,第 4 题评论区普遍认为是 1 字头,纯纯手速场。 小彭的 Android 交换群 02 群来了,公众号回复 “加群” 退出咱们~ 2578. 最小和宰割题目地址https://leetcode.cn/problems/split-with-minimum-sum/ 题目形容给你一个正整数 num ,请你将它宰割成两个非负整数 num1 和 num2 ,满足: num1 和 num2 间接连起来,失去 num 各数位的一个排列。 换句话说,num1 和 num2 中所有数字呈现的次数之和等于 num 中所有数字呈现的次数。num1 和 num2 能够蕴含前导 0 。请你返回 num1 和 num2 能够失去的和的 最小 值。 留神: num 保障没有前导 0 。num1 和 num2 中数位程序能够与 num 中数位程序不同。 题解(排序 + 贪婪)第一题绝对有点思维。 思考 1:越高位的数字对后果的影响越大,所以优先排列最小的数字;思考 2:如果划分两个数字的长度不均,会放大最终的值;算法:对数字排序,从小到大别离排列到两个数字上。 class Solution { fun splitNum(num: Int): Int { val array = "$num".toCharArray() array.sort() var num1 = 0 var num2 = 0 for (index in array.indices step 2) { num1 = num1 * 10 + (array[index] - '0') if (index + 1 < array.size) { num2 = num2 * 10 + (array[index + 1] - '0') } } return num1 + num2 }}简化写法: ...

March 5, 2023 · 4 min · jiezi

关于android:Android-startActivityForResult废弃了代替方案案例

安卓我的项目compileSdk为32,在应用startActivityForResult()办法时发现Android studio提醒此办法曾经废除了。 目前的代替计划案例。// 确保 app 的 build.gradle中曾经引入了androidx.appcompat:appcompatdependencies { implementation 'androidx.appcompat:appcompat:1.4.1' // 确定 }从A跳到B,A页面逻辑package com.example.test1;import androidx.activity.result.ActivityResult;import androidx.activity.result.ActivityResultCallback;import androidx.activity.result.ActivityResultLauncher;import androidx.activity.result.contract.ActivityResultContracts;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Intent;import android.graphics.Color;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import android.widget.Toast;import com.example.test1.ui.login.LoginActivity; // B页面例子import com.google.android.material.snackbar.Snackbar;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static String TAG = "MainActivity"; private ActivityResultLauncher<Intent> register; @SuppressLint("ResourceAsColor") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.my_button).setOnClickListener(this); register = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { Log.i(TAG, "onActivityResult: _____" + result); if (result != null) { Intent intent = result.getData(); if (intent != null && result.getResultCode() == Activity.RESULT_OK) { Bundle myBundle = intent.getExtras(); String my_name = myBundle.getString("my_name"); String my_sex = myBundle.getString("my_sex"); // 下一个Activity回退后 在此获取返回的值 Log.i(TAG, "onCreate: 获取返回传值my_name__________" + my_name); // ___获取返回传值my_namezhangsan000 Log.i(TAG, "onCreate: 获取返回传值my_sex__________" + my_sex); // ___获取返回传值my_sex男 } } } }); } @Override public void onClick(View view) { if (view.getId() == R.id.my_button) { Intent intent = new Intent(this, LoginActivity.class); // 用register.launch跳转至B register.launch(intent); } }}从A跳到B,B页面回退逻辑// B页面的后退逻辑public void myBack(View view) { Intent intent = new Intent(); Bundle bundle = new Bundle(); bundle.putString("my_name", "zhangsan000"); bundle.putString("my_sex", "男"); intent.putExtras(bundle); // 携带用意返回上一个页面 RESULT_OK代表解决胜利了 setResult(Activity.RESULT_OK, intent); // 完结以后页面 finish();};

March 5, 2023 · 1 min · jiezi

关于android:巧用别名和-sh-脚本adb-快速截图和录屏提高你的效率

前言在平时开发过程中,咱们常常须要截图和录制视频,尤其是客户端开发和测试。 可能有一些人的姿态是这样的。在电脑上开个模拟器,应用第三方工具后进行截图和录屏。还有一种最原始的形式,在手机上截图和录制视频,而后再通过 QQ 等工具发送到电脑,这多累呀。 其实,有一种很简便的形式,那就是说通过别名和 adb,一个简略命令,让你疾速截图和录制视频,如 adbshot, adbrecord。上面让咱们一起来看一下,怎么实现? adb 命令和录制视频adb 命令截图第一种办法 #(保留到SDCard)adb shell /system/bin/screencap -p /sdcard/screenshot.png# 从SD卡导出到电脑,留神/Users/junxu 为电脑门路,必须存在adb pull /sdcard/screenshot.png /Users/junxu如果你想删除手机上的图片,那么你能够应用这个命令来删除 adb shell rm /sdcard/screen.png开始录制命令:adb shell screenrecord --time-limit 10 /sdcard/demo.mp4阐明:录制手机屏幕,视频格式为mp4,寄存到手机sd卡里,默认录制工夫为180s mac 设置别名1、根本语句 alias lts ="cd /Users/junxu/Desktop/sh"2、批改文件 vi ~/.bash_profile退出 alias lts="cd /data" 保留 3、使别名命令失效 source ~/.bash_profile4、在命令行输出lts 就能够达成 cd /Users/junxu/Desktop/sh的成果 配合别名,疾速截图和录屏截图减少截图别名 alias adbshot="sh /Users/junxu/Desktop/sh/shot.sh"截图 SH 脚本 #!/bin/bash# Android截图,定位和预览默认开启,如果想敞开,能够正文echo "第一个参数为:$1";dd=`date +%Y-%m-%d-%H-%M-%S`pwd=`pwd`adb shell screencap -p /sdcard/screenshot.pngadb pull /sdcard/screenshot.pngadb shell rm /sdcard/screenshot.pngmv screenshot.png $dd.pngecho "截图已保留为当前目录下的"$pwd$dd.png# 批改图片尺寸,长或宽最大不超过960,等比缩放echo "压缩图片..."sips -Z 960 $pwd/$dd.png# 定位到文件open ./$dd.png -R# 关上预览open -a Preview $dd.png# 复制到剪切板osascript -e 'on run args' -e 'set the clipboard to POSIX file (first item of args)' -e end $pwd/$dd.pngecho "截图已复制到剪切板"记得给 SH 脚本减少可执行权限。 ...

March 1, 2023 · 1 min · jiezi

关于android:Switchquery移动端秒级配置触达平台

作者:京东批发 胡本奎 一 背景随着挪动互联网的疾速倒退,为满足各类用户及人群的体验需要,挪动端的开发者们开发了丰富多彩的体验与性能。同时对于疾速管制各类性能的切换、灰度,降级等能力的要求也越来越高,例如通过配置疾速关上某个灰度性能,通过配置信息的实时触达敞开某个引起App解体的性能等等。因而须要一套具备实时触达配置信息到挪动端的能力,消沉本的配置平台来解决。 咱们研发了Switchquery配置平台,它是一套具备秒级变更能力,助力业务疾速变更,让配置信息在App运行中秒级失效,同时晋升配置信息触达率,对立治理的配置平台。 二 技术原理1 触达技术选型在Switchquery配置平台外围能力中,实时触达的能力尤为重要,目前业界支流的触达技术计划次要有以下几种形式: 1) 推送push 音讯: push音讯以后曾经成为实时推送营销信息、重要告诉的最次要伎俩之一,push音讯领有较强的实时性,而理论的挪动端的利用场景中,push音讯多用于营销计划或重要信息的告诉,很少应用此通道来作为研发配置信息的触达通道,其会产生UI交互的变动。另外push音讯依赖于用户关上告诉权限开关,而业内广泛关上告诉开关权限的比例低于50%,因而大部分用户无奈触达。 2) tcp或websocket长连贯: 通过建设一条客户端到服务端之间的长连贯通道,此计划能够在产生配置信息变更后实时的将信息传递至客户端,然而须要消耗较大的服务器资源,来保护一条长连贯通道。 3) 轮询: 客户端以肯定的工夫距离向服务端发出请求,通过频繁申请的形式来放弃客户端和服务器端的信息同步,这种同步计划的最大问题是当客户端以固定频率向服务器发动申请的时候,服务器端的数据可能并没有更新,这样会带来很多有效的网络传输。 2 实现原理2.1 实时触达计划因为推送push音讯计划存在触达比例低的问题,长链接存在消耗服务器资源的毛病,同时轮询的计划也存在很多有效的网络传输等弊病,因而以上三种计划都不是Switchquery 配置平台的触达计划的最佳技术选型。通过调研,咱们采取了一种配置信息从服务端实时触达到客户端的新计划,计划的具体形容为: 先搭建一个信息配置管理CMS平台,同时构建一个客户端获取配置信息的客户端组件,由用户在CMS配置信息,而后由CMS后盾将配置信息的版本号信息同步至对立网关,所有客户端申请达到对立网关,并在返回的接口数据的header内都会携带最新的版本号至客户端,客户端比照发现新的版本号比缓存的版本大则申请配置信息拉取Switchquery配置接口,这样只有App关上就会存在接口携带变动标记返回,这样就会触发客户端被动发动申请更新配置信息,进步了实时性,不受push开关权限管制和影响,不须要额定打造长连贯通道,具备低成本,实时性低等长处。以下是Switchquery配置平台的时序图: 1) 用户在Switchquery CMS 后盾配置相干信息,目前平台上反对配置布尔类型、整型、字符串等类型的配置信息,能够配置App版本失效区间,按设施号灰度比例,iOS或者安卓平台的设定,失效白名单等相干信息。 2) Switchquery CMS后盾配置信息并提交和保留实现后,由CMS配置后盾将新的版本号写入到对立网关后盾(所有客户端到服务端的http申请都会通过对立网关,所有服务端返回到客户的http申请响应都会通过对立网关),对立网关记录下数据版本号,客户端的所有接口申请的响应header减少一个字段x-switch-config,此字段会携带回配置信息的版本号至客户端。 3) Switchquery CMS配置后盾实现信息配置后,后盾会基于以后工夫戳,生成一个新的配置信息版本号,同时将这些配置的静态数据写入到服务端内存缓存内,同步刷新配置开关接口。 4) Switchquery CMS配置后盾将配置信息数据写入和保留一份静态数据json到CDN,避免接口降级或者失败当前能够降级从CDN拉取配置信息数据。 5) 网关会将版本号下发至客户端网络组件,网络组件在承受到网络申请返回后,首先会解析网络申请的响应header,如果解析到关键字将其对应的value一起解析封装后发动一个全局告诉。 6) 配置客户端组件在监听到告诉后,与本地曾经缓存的配置信息数据版本号进行比对,雷同则不解决,大于本地版本号则发动配置信息拉取申请,这样即可获取到最新的开关配置信息并缓存在磁盘。 7) 客户端在接口降级或者失败后会从CDN拉取配置数据信息。 此种触达形式只有客户端关上即会触发申请至对立网关,随即就能够依据变动状况来决定是否更新最新的配置接口数据,无需push告诉,无需建设长连贯通道,成本低,实时性高。 2.2 流程架构设计 1) 用户在CMS配置平台进行信息配置后,配置后盾接口对配置信息进行比照,包含配置信息中的开关的状态,开关值等要害信息,如果没发生变化,则完结;发生变化则判断此次变更间隔上一次变更是否到了n秒,间隔n秒内则不会触发配置信息变更同步,间隔n秒外则触发配置信息同步,触发网关和后盾接口数据发生变化。 2) CMS触发变动将新的版本号传递至对立网关,对立网关会做数据版本号的存储,同时会将对立网关的所有机器内存里都存储一份最新的版本号。 也会将数据变更信息同步到配置后盾接口,同步写入一份json静态数据到CDN,这个是为了避免配置信息接口服务端挂了后能够走CDN兜底。 3) 客户端任意接口申请都会通过对立网关,所有申请的返回也会通过对立网关返回,在返回的响应header内新增一个x-switch-config字段,其value是一段字符串,由下划线隔开,格局如: switch_version_randomtime_reserved,第一个字段switch=0/1,其中0示意此能力对立降级敞开,1示意此能力关上;第二个字段version就是配置信息的数据版本号,目前是按工夫戳的模式标识版本号;第三个字段randomtime示意客户端获取到版本号变动差别后并非立即申请,会提早[0,randomtime]之间的一个随机工夫后才发动申请,这个是为了升高霎时尖峰流量的产生;第四个字段是留作将来应用。 4) 客户端网络框架在客户端会不间断随机播送全局告诉, 开关客户端组件收到告诉后,获取到对立网关的返回数据,解析网络接口返回的header局部,获取x-switch-config字段,解析字段中的value,如果是降级,则完结,如果版本号没有发生变化,则完结,如果非限流同时 switch=1,并且本地的缓存的开关version小于解析后的version,则依据randomtime随机数发动客户端申请;如果服务端返回了特定的限流码则客户端间接从CDN拉取配置信息数据并更新本地缓存数据,如果服务端失常返回则获取开关数据并更新本地缓存。 3 技术优化在Switchquery 配置平台的设计开发中,从实时性,性能,老本,持重等多维度进行了优化,具体的优化措施如下: 1) 思考到实时性与机器老本的均衡,咱们在CMS配置端做了聚合n秒后才将配置变更同步至对立网关,次要为了避免多个用户在很近的工夫内做了多个批改,会导致对立网关侧频繁的接管到不同的版本号,进而引起客户端频繁的发动申请,导致配置信息服务端的流量陡增,目前的经验值是n=5秒。 2) 思考性能与机器老本的均衡,客户端会依据randomtime来随机发动申请,是为了打散申请发动机会,理论教训咱们发现5s会增日常2倍左右的QPS,10s会减少日常1.5倍左右,理论各个场景能够依据本身的服务器机器数量与老本来动静决定抉择设置多长时间。 ...

March 1, 2023 · 1 min · jiezi

关于android:可以安装上万插件且基于chromium内核开发的手机浏览器狐猴浏览器

当初反对装置插件的手机浏览器越来越多了,包含iOS端的Safari也反对扩大。然而安卓软件市场内各种反对扩大的浏览器仿佛都大同小异,然而最近被敌人举荐的狐猴浏览器是我用下来感觉还挺不错的。 首先,狐猴反对Chrome和Edge两个扩大商店的扩大,在扩大的齐全度方面我认为稍逊一筹,也不便了不会魔法的用户。 其次,无论是扩大的装置还是应用,都更合乎国内用户的应用习惯。界面简洁大气,能够很直观地看到正在运行的扩大的状态。以油猴插件为例,只须要点击图标,就能够间接在上拉页面中看到油猴脚本的运行状态,不会笼罩掉原本正在浏览的页面。 扩大治理中,狐猴浏览器还反对从内部加载扩大,只须要关上开发者模式就能够。 狐猴浏览器自身就带有十分弱小的性能,例如暗黑模式、明码管理工具、多个搜索引擎切换、网页翻译、网页内查找等等。除了这些外,还有许多依附插件能够实现的性能,比方倍速视频、沉迷式浏览、批量下载图片、下载视频等。 我认为一个功能强大且不断更新的手机浏览器放在手机里总有用得上的时候,尽管体积不小,然而对于这些性能来说也是正当的。并且在都是大内存手机的时代,狐猴的体积也还是能够承受的。

February 28, 2023 · 1 min · jiezi

关于android:在线文本翻译能力新增14个直译模型打造以中文为轴心语言的翻译系统

经济全球化的明天,人们在工作和生存中常常会与外语打交道。相较流传性较广的英语而言,其余语种的辨认和浏览对大多数人来说是一件难事,此时就须要借助语言翻译软件来帮忙了解。 华为 HMS Core 机器学习服务(ML Kit)翻译性能提供了多种翻译模式,不仅能够满足利用出行购物、网络社交等日常场景,还提供办公文档、视频字幕等专业翻译服务,满足多种语言和场景利用。其中在线文本翻译能力反对15国语种中文互译,满足邮件翻译、语音翻译、浏览器翻译、同传翻译等场景。 以后支流的翻译模式大都以语料资源较为丰盛的英文作为两头语言进行“桥接”翻译,然而经英文转移后翻译精度有所损失,且计算资源加倍执行成果升高。 基于此,HMS Core机器学习服务对在线文本翻译能力进行降级,在原有的8国语言上又新增中意、中阿、中波、中荷、意中、阿中、波中、荷中 、中马、中泰、中越、越中、泰中、马中十四个直译模型,反对TOP15语种中文互译。相较于英文桥接翻译,中文直译模型可实现每秒并发300字符,端到端翻译速度小于150ms,翻译时延升高100%,翻译速度更快;针对中文特色词、俚语的翻译后果更纯粹,翻译品质更优。在线文本翻译能力分批次打造可信中文直译零碎,确保中文和TOP语种的互译成果优于友商,打造差异化竞争力,能够满足中企出海或外企入华等对翻译要求更高场景的需要。 产品劣势个性化术语翻译 用户可自行提供术语以优化翻译后果,华为术语翻译引擎提供可定制的个性化术语翻译能力。 中文为轴心的机器翻译 反对TOP15语种中文互译,让翻译时延更低,品质更优。在WMT 2021 国内机器翻译大赛三角翻译工作中,取得俄到中翻译第一名。 响应实时稳固 全流程毫秒级响应,译文后果精准晦涩。寰球四大站点部署,助力品牌出海无忧。 多语言翻译品质当先 依靠先进的机器翻译技术,联合各垂域大数据劣势,满足用户在多畛域、多场景下的翻译需要。在IWSLT 2020国内翻译大赛中,取得中到英字幕翻译第一名。 开发步骤开发筹备在进行开发之前,您须要实现必要的开发筹备工作,同时请确保您的工程中曾经配置HMS Core SDK的Maven仓地址,并且实现了本服务的SDK集成。 在线文本翻译能力集成请参见云端鉴权信息应用须知,设置您利用的鉴权信息。创立在线文本翻译器。能够通过文本翻译器自定义参数类MLRemoteTranslateSetting创立翻译器。// 应用自定义的参数配置创立文本翻译器。MLRemoteTranslateSetting setting = new MLRemoteTranslateSetting .Factory() // 设置源语言的编码,应用ISO 639-1规范(中文繁体应用BCP-47规范)。此设置为可选项,如果不设置,将自动检测语种进行翻译。 .setSourceLangCode("zh") // 设置目标语言的编码,应用ISO 639-1规范(中文繁体应用BCP-47规范)。 .setTargetLangCode("en") .create();MLRemoteTranslator mlRemoteTranslator = MLTranslatorFactory.getInstance().getRemoteTranslator(setting);可通过上面的办法查问在线翻译所反对的语种。异步办法示例代码: MLTranslateLanguage.getCloudAllLanguages().addOnSuccessListener( new OnSuccessListener<Set<String>>() { @Override public void onSuccess(Set<String> result) { // 胜利获取在线翻译所反对的语种。 }});同步办法示例代码: try { Set<String> result = MLTranslateLanguage.syncGetCloudAllLanguages(); // 胜利获取在线翻译所反对的语种。} catch (MLException e) { // 获取在线翻译所反对的语种出现异常。}进行在线文本翻译(错误码信息可参见:机器学习服务错误码)。异步办法示例代码: ...

February 28, 2023 · 1 min · jiezi

关于android:LeetCode-周赛-334在算法的世界里反复横跳

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。大家好,我是小彭。 明天是 LeetCode 第 334 场周赛,你加入了吗?这场周赛考查范畴比拟根底,整体难度比拟均匀,第一题难度偏高,第四题须要咱们在算法里实现 “重复横跳”,十分有意思。 小彭的 Android 交换群 02 群来了,公众号回复 “加群” 退出咱们~ 2574. 左右元素和的差值(Easy)题目地址https://leetcode.cn/problems/... 题目形容给你一个下标从 0 开始的整数数组 nums ,请你找出一个下标从 0 开始的整数数组 answer ,其中: answer.length == nums.lengthanswer[i] = |leftSum[i] - rightSum[i]|其中: leftSum[i] 是数组 nums 中下标 i 左侧元素之和。如果不存在对应的元素,leftSum[i] = 0 。rightSum[i] 是数组 nums 中下标 i 右侧元素之和。如果不存在对应的元素,rightSum[i] = 0 。返回数组 answer 。 题解简略模拟题,应用两个变量记录前后缀和。 class Solution { fun leftRigthDifference(nums: IntArray): IntArray { var preSum = 0 var sufSum = nums.sum() val n = nums.size val result = IntArray(n) for (index in nums.indices) { sufSum -= nums[index] result[index] = Math.abs(preSum - sufSum) preSum += nums[index] } return result }}复杂度剖析: ...

February 27, 2023 · 7 min · jiezi

关于android:华为Push用户增长服务精准触达加速增长

速戳理解华为Push用户增长服务:通过精细化经营,助力开发者高效实现用户增长,晋升用户活跃度和粘性! 单干征询请点此链接 理解更多详情>> 拜访华为开发者联盟官网 获取开发领导文档 华为挪动服务开源仓库地址:GitHub、Gitee 关注咱们,第一工夫理解 HMS Core 最新技术资讯~

February 27, 2023 · 1 min · jiezi

关于android:Android-启动优化三-AnchorTask-使用说明

微信公众号:徐公,本文首发我的微信公众号,有趣味的能够点此扫码关注前两篇博客介绍了 Android 启动优化多线程异步加载依赖问题的解决方案 - 有向无环图,以及如何实现有它。明天,让咱们一起来看一下,在 Android 实战中,怎么实现。 Android 启动优化(一) - 有向无环图 Android 启动优化(二) - 拓扑排序的原理以及解题思路 简介Android 启动优化,大家第一工夫可能会想到异步加载。将耗时工作放到子线程加载,等到所有加载工作加载实现之后,再进入首页。 多线程异步加载计划的确是 ok 的。但如果遇到前后依赖的关系呢。比方工作2 依赖于工作 1,这时候要怎么解决呢。 这时候就能够应用 AnchorTask 解决,它的实现原理是构建一个有向无环图,拓扑排序之后,如果工作 B 依赖工作 A,那么 A 肯定排在工作 B 之后。 根本应用第一步:在 moulde build.gradle 配置近程依赖 implementation 'com.xj.android:anchortask:0.1.0'最新的版本号能够看这里 lastedt version 第二步:自定义 AnchorTaskB,继承 AnchorTask,重写相应的办法 class AnchorTaskB : AnchorTask() { override fun isRunOnMainThread(): Boolean { return false } override fun run() { val start = System.currentTimeMillis() try { // 在这里进行操作,这里通过睡眠模仿耗时操作 Thread.sleep(300) } catch (e: Exception) { } com.xj.anchortask.library.log.LogUtils.i( TAG, "AnchorTaskOne: " + (System.currentTimeMillis() - start) ) } // 返回依赖的工作,这里是通过 class name 去找到对应的 task override fun getDependsTaskList(): List<Class<out AnchorTask>>? { return ArrayList<Class<out AnchorTask>>().apply { add(AnchorTaskA::class.java) } }}如果工作 C 依赖工作 B,工作 A,能够这样写 ...

February 25, 2023 · 2 min · jiezi

关于android:FAQ获取Push-Token失败如何进行排查

一、 获取Push Token的形式获取Push Token有两种形式:一种是调用getToken办法向Push服务端申请Token,当getToken办法返回为空时,Token可通过onNewToken办法返回,因而须要实现onNewToken办法;另一种是主动初始化,Token通过onNewToken办法返回。这两种办法的具体阐明可看获取和登记Token文档:获取和登记Token。 二、 获取Push Token失败的景象获取Push Token失败大抵有两种景象:一种是获取Token的接口执行失败,谬误会在日志中显示,有相应的错误码打印;另一种是获取Token的接口执行胜利,没有报错,然而getToken办法返回为空,onNewToken办法也没有被调用。 三、 分景象进行排查如果有报错,须要找到报错形容和错误码,参考常见错误码阐明文档:常见错误码,依据报错形容和常见错误码阐明文档中对应错误码的解决办法进行排查,大部分问题都能够失去解决。 比拟典型的案例:开发者依照对应错误码的解决办法进行排查,无奈解决问题,起初和开发者要了手机端抓取的日志,从日志中看到申请Token应用的appid不是利用对应的appid。所以肯定要保障应用的agconnect-services.json文件是对应利用最新的文件,能够从AGC管制台上新下载一份;并且保障利用中所有应用到的appid都是对的,能够用全局搜寻进行查找。有些开发者的利用可能是多集体共同开发的,变量命名可能不统一,无奈搜寻所有用到的appid,这种状况下能够通过手机端日志确认应用的appid是否正确。 日志抓取办法:zaaxz adb shell setprop log.tag.hwpush VERBOSEadb logcat -v threadtime 1> D:\hwpush.log 2、尝试复现遇到的问题场景。 3、按快捷键“Ctrl+C”实现日志抓取。 查找要害日志: 搜寻api_name:push.gettoken关键字,找到如上图所示的这行日志,error_code是申请Token失败时返回的错误码,app_id是用来申请Token的appid,pkg_name是利用的包名,查看app_id值是否为对应利用的appid,如果不是,能够应用这个app_id在利用的工程中进行全局搜寻,排查在哪个中央应用了这个值,并进行批改。 如果获取token的接口执行胜利,没有报错,onNewToken办法也没有被调用,请查看代码中继承了HmsMessageService的自定义类,看下自定义的类中除了重写了配置Manifest文件文档中阐明的用于接管透传音讯、获取Token的办法外,是否曾经重写其余办法,如果有请去掉,其余办法不须要重写,而且重写可能会导致类中的办法不会被调用。如果继承HmsMessageService的类实现没有问题,请排查工程中定义了几个继承HmsMessageService的类,如果定义了多个继承HmsMessageService的类,也会导致实现的办法不会被调用,继承HmsMessageService的类只能有一个。 典型案例: 开发者应用三方推送,三方推送的SDK中曾经定义了一个继承HmsMessageService的类,这种状况就不须要再定义继承HmsMessageService的类,须要开发者去征询三方推送的技术支持要怎么应用他们定义的这个类。能够通过反编译查看Android申明文件,确定三方推送的SDK中是否定义了继承HmsMessageService的类。能够通过查看手机端日志确定有几个继承HmsMessageService的类,日志抓取办法同上,上面说一下怎么看要害日志。 查找要害日志: 搜寻HmsMessageService num is关键字,找到如上图所示的日志,联合日志上下文中的packageName确定对应利用的日志,HmsMessageService num is前面的数值就是继承HmsMessageService的类的数量,如果不为1,请排查工程代码,并删除多余的类。 理解更多详情>> 拜访华为开发者联盟官网 获取开发领导文档 华为挪动服务开源仓库地址:GitHub、Gitee 关注咱们,第一工夫理解 HMS Core 最新技术资讯~

February 23, 2023 · 1 min · jiezi

关于android:2023-年-Android-如何学习一位-6-年大厂的-Android-老哥跟你聊聊

本文首发我的微信公众号:程序员徐公度日如年,光阴似箭,工夫真的过得飞快。加上实习,从事 Android 开发,差不多有 5 年了,在这里,我分享一下我的教训,在 Android 的学习路上,我是站在伟人的肩膀上成长起来的。 大略分为三个局部 一、Android 职业规划<br/>二、Android 学习路线<br/>三、如何进入大厂<br/>Android 成长生涯 1-3 年前 3 年,我感觉是咱们成长最快的时候。 尤其是刚开始工作的一年,刚开始接触我的项目,咱们会接触到很多新常识,比拟网络框架的封装,Android 架构 MVVN,MVC,MVP 等。 这段期间是咱们提高最快的时候,因为很多货色咱们都不会,咱们会逼着本人去学习。 第二到第三年,也是咱们成长的关键时期。这时候,在我的项目中,咱们根本会本人独立负责需要。这时候的咱们,大多数基本功能都能够本人独立实现。须要留神的是代码格调和代码思维的造就。 代码格调,指的是编码习惯。比方办法命名,办法的正当拆分,适当增加注解,正文。听起来可能会很虚,然而千万别小看这些细节。反正我在组里见过一些工作五六年的,代码一坨一坨的,像 si 一样。 代码思维,有点相似于人的视线和思考形式吧。很多时候,实现某个成果,有很多种计划。咱们为了应酬需要,可能会轻易抉择一种,没有去理解其余计划。而这恰好错过了咱们成长的最佳时期。 记住,永远别给本人设限,或者在编程的路上会遇到很多问题,然而总会有解决办法的,而这取决你的态度。 3-5 年这个期间,不出意外,咱们根本都是高级工程师了。这时候大多数人会遇到瓶颈,不晓得学些什么好。如同什么都会,然而不够深刻。我也遇到这样的状况,当初正在深挖。 这方面我临时也给不了太多意见,只能说,抉择一个方向,静下心来,去学习,置信能播种到咱们想要的。 学习方向有很多,比方 Android 性能优化(启动,卡顿, Crash 治理), JNI C++,gradle 打包,编译速度,音视频等等,这些都是大的方向。 最近写的一些文章,自我感觉还行,有趣味的能够看看。 Android 启动优化(一) - 有向无环图 Android 启动优化(二) - 拓扑排序的原理以及解题思路 Android 启动优化(三)- AnchorTask 开源了 Android 启动优化(四)- AnchorTask 是怎么实现的 Android 启动优化(五)- AnchorTask 1.0.0 版本正式公布了 Android 启动优化(六)- 深刻了解布局优化 5 年之后技术人的四大前途,你适宜哪一个 大多数技术人,个别会有以下方向。 第一:成为技术大神,比方架构师,及技术专家等。第二:技术治理,比方技术总监等。第三:技术转型,如转项目管理,产品等,你牛逼的话,说不定下一个张小龙就是你(哥们,想多了,那有这么容易)。第四:自主守业,做自媒体等我目前来说,可能会抉择第一条路吧,成为一名技术专家。 在技术的路上,或者会很累,很难,可那又怎么呢 ...

February 22, 2023 · 1 min · jiezi

关于android:Android-启动优化二-拓扑排序的原理以及解题思路

Android 启动优化(一) - 有向无环图 Android 启动优化(二) - 拓扑排序的原理以及解题思路 Android 启动优化(三) - AnchorTask 应用阐明 Android 启动优化(四)- 手把手教你实现 AnchorTask Android 启动优化(五)- AnchorTask 1.0.0 版本更新了 Android 启动优化(六)- 深刻了解布局优化 这几篇文章从 0 到 1,解说 DAG 有向无环图是怎么实现的,以及在 Android 启动优化的利用。 举荐理由:当初挺多文章一谈到启动优化,动不动就聊拓扑构造,这篇文章从数据结构到算法、到设计都给大家说分明了,开源我的项目也有十分强的借鉴意义。 前言春节之前,更新了一篇博客 Android 启动优化(一) - 有向无环图,反应还不错,明天,让咱们一起来看一下,怎么用代码实现有向无环图。 基本概念拓扑排序的英文名是 Topological sorting。 拓扑排序要解决的问题是给一个图的所有节点排序。有向无环图才有拓扑排序,非有向无环图没有。 换句话说,拓扑排序必须满足以下条件 图必须是一个无环有向图。序列必须满足的条件: 每个顶点呈现且只呈现一次。若存在一条从顶点 A 到顶点 B 的门路,那么在序列中顶点 A 呈现在顶点 B 的后面。实战咱们已 leetcode 下面的一道算法题目作为切入点进行解说。 leeocode 210: https://leetcode-cn.com/probl... eg: 当初你总共有 n 门课须要选,记为 0 到 n-1。 在选修某些课程之前须要一些先修课程。 例如,想要学习课程 0 ,你须要先实现课程 1 ,咱们用一个匹配来示意他们: [0,1] 给定课程总量以及它们的先决条件,返回你为了学完所有课程所安顿的学习程序。 ...

February 22, 2023 · 3 min · jiezi

关于android:LeetCode-周赛-333你管这叫-Medium-难度

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。大家好,我是小彭。 上周是 LeetCode 第 333 场周赛,你加入了吗?这场周赛品质很高,但难度标得不对,我真的会谢。算法解题思维须要长时间锤炼,退出咱们一起刷题吧~ 小彭的 Android 交换群 02 群曾经建设啦,公众号回复 “加群” 退出咱们~ 2570. 合并两个二维数组 - 求和法(Easy)题目地址https://leetcode.cn/problems/... 题目形容给你两个 二维 整数数组 nums1 和 nums2. nums1[i] = [idi, vali] 示意编号为 idi 的数字对应的值等于 vali 。nums2[i] = [idi, vali] 示意编号为 idi 的数字对应的值等于 vali 。每个数组都蕴含 互不雷同 的 id ,并按 id 以 递增 顺序排列。 请你将两个数组合并为一个按 id 以递增顺序排列的数组,并合乎下述条件: 只有在两个数组中至多呈现过一次的 id 能力蕴含在后果数组内。每个 id 在后果数组中 只能呈现一次 ,并且其对应的值等于两个数组中该 id 所对应的值求和。如果某个数组中不存在该 id ,则认为其对应的值等于 0 。返回后果数组。返回的数组须要按 id 以递增顺序排列。 题解简略模拟题,应用双指针合并数组即可。 class Solution { fun mergeArrays(nums1: Array<IntArray>, nums2: Array<IntArray>): Array<IntArray> { val n = nums1.size val m = nums2.size val result = LinkedList<IntArray>() var index1 = 0 var index2 = 0 while (index1 < n && index2 < m) { val e1 = nums1[index1] val e2 = nums2[index2] if (e1[0] == e2[0]) { result.add(intArrayOf(e1[0], e1[1] + e2[1])) index1++ index2++ } else if (e1[0] < e2[0]) { result.add(e1) index1++ } else { result.add(e2) index2++ } } while (index1 < n) { result.add(nums1[index1++]) } while (index2 < m) { result.add(nums2[index2++]) } return result.toTypedArray() }}复杂度剖析: ...

February 21, 2023 · 8 min · jiezi

关于android:LeetCode-双周赛-98脑筋急转弯转不过来

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。大家好,我是小彭。 昨晚是 LeetCode 第 98 场双周赛,你加入了吗?这场周赛须要脑筋急转弯,转不过去 Medium 就会变成 Hard,转得过去就变成 Easy。 小彭的 Android 交换群 02 群曾经建设啦,公众号回复 “加群” 退出咱们~ 2566. 替换一个数字后的最大差值(Easy)题目地址https://leetcode.cn/problems/maximum-difference-by-remapping-a-digit/ 题目形容给你一个整数 num 。你晓得 Danny Mittal 会偷偷将 0 到 9 中的一个数字 替换 成另一个数字。 请你返回将 num 中 恰好一个 数字进行替换后,失去的最大值和最小值的差位多少。 留神: 当 Danny 将一个数字 d1 替换成另一个数字 d2 时,Danny 须要将 nums 中所有 d1 都替换成 d2 。Danny 能够将一个数字替换成它本人,也就是说 num 能够不变。Danny 能够将数字别离替换成两个不同的数字别离失去最大值和最小值。替换后失去的数字能够蕴含前导 0 。Danny Mittal 取得周赛 326 前 10 名,让咱们祝贺他。题解(字符串操作)技巧:将整型转换为字符串可能更不便地批改具体位置。简略模拟题,有 2 个思路: 思路 1 - 暴力枚举:尝试枚举每类的数字,将其替换为 9 获得最大值,将其替换为 0 获得最小值,最初取所有计划的最大值和最小值取差值;思路 2 - 贪婪思路:替换越凑近 “高位” 的数字可能使得差值越大,所以咱们将从高位开始的首个非 9 数字替换为 9(例如 90 替换为 99)必然失去最大值,将从高位开始的首个数字替换为 0(例如 90 替换为 00)必然失去最小值。// 思路 1class Solution { fun minMaxDifference(num: Int): Int { val numStr = "$num" var max = num var min = num for (element in numStr) { max = Math.max(max, numStr.replace(element, '9').toInt()) min = Math.min(min, numStr.replace(element, '0').toInt()) } return max - min }}复杂度剖析: ...

February 20, 2023 · 9 min · jiezi

关于android:FAQ集成分析服务的常见问题及解决方案

常见问题一:如何验证Analytics是否上报/接入胜利?以及要害日志含意是什么?在初始化Analytics SDK前增加SDK日志开关如下:HiAnalyticsTools.enableLog ();2.初始化SDK代码如下: HiAnalyticsInstance instance = HiAnalytics.getInstance (this);3.运行利用通过过滤日志查看是否有胜利上报的要害日志.。 未上报/接入胜利: 日志中会呈现错误码局部日志可能是红色提醒,请参见SDK错误码、集成调测类问题查看是否有相干解决方案。 胜利上报要害日志如下: HiAnalyticsSDK: SendMission=> events PostRequest sendevent TYPE : oper, TAG : _openness_config_tag, resultCode: 200 ,reqID:xxx开启利用调试每上报一次会呈现如下日志: HiAnalyticsSDK: DeviceToolsKit=> debugMode enabled.利用调试不反对上报某事件会呈现如下提醒: HiAnalyticsSDK: ReportRingback=> do not enable APIEvt in debug model常见问题二:初始化SDK时报错“client token request miss client id”怎么办?【报错信息】 HiAnalyticsSDK: TokenAssignment=> SE-003|get token exception on the AGC! java.lang.IllegalArgumentException: client token request miss client id, please check whether the 'agconnect-services.json' is configured correctly【问题根因】 在“我的项目设置”页面中,“利用”栏下的“agconnect-services.json”配置文件右侧的“不蕴含密钥”开关被关上了,配置文件中去除了Client密钥、API Key等密钥,但未自行调用AGC SDK的接口手动配置密钥信息。 ...

February 20, 2023 · 1 min · jiezi

关于android:面试官-https-真的安全吗可以抓包吗如何防止抓包吗

往期文章 Android 面试必备 - http 与 https 协定 Android 面试必备 - 计算机网络基本知识(TCP,UDP,Http,https) Android 面试必备 - 线程 Android 面试必备 - JVM 及 类加载机制 Android 面试必备 - 零碎、App、Activity 启动过程 面试官系列- 你真的理解 http 吗 面试官问, https 真的平安吗,能够抓包吗,如何避免抓包吗 前言转眼间,2020 年已过来一大半了,2020 年很难,各企业裁员的音讯蛮多的,晋职,不发年终奖等等。2020 年的确是艰巨的一年。然而生存总是要持续,工夫不给你丧的机会!如果咱们能保持下来,一直进步本人,说不定会有新的机会。 面试中,网络(http, https, tcp, udp), jvm, 类加载机制等这些根底的知识点是高频呈现的,每个程序员都能说上好多。但不肯定说到重点,以及了解背地的原理。 我在面试的过程中也常常被问到,于是总结记录了下来。千万不要小瞧这些根底,有时候,你算法,我的项目教训都过了,然而根底答得不太好。后果可能会通过,但这必定会影响你的评级,这是特地吃亏的。所以,不如花点工夫背一下,了解一下背地的原理。 举一个简略的例子, https 连贯过程是怎么的,应用了了哪种加密形式,能够抓包吗,怎么避免抓包,你是否可能对答如下。 废话不多说,开始进入注释。 背景咱们晓得,http 通信存在以下问题: 通信应用明文可能会被窃听不验证通信方的身份可能遭逢假装无奈证实报文的完整型,可能已遭篡改应用 https 能够解决数据安全问题,然而你真的了解 https 吗? 当面试官间断对你收回灵魂诘问的时候,你能对答如流吗 什么是 https,为什么须要 httpshttps 的连贯过程https 的加密形式是怎么的,对称加密和非对称加密,为什么要这样设计?内容传输为什么要应用对称秘密https 是相对平安的吗https 能够抓包吗如果你能对答自若,祝贺你,https 你曾经把握得差不多了,足够应酬面试了。 什么是 https简略来说, https 是 http + ssl,对 http 通信内容进行加密,是HTTP的平安版,是应用TLS/SSL加密的HTTP协定 ...

February 19, 2023 · 1 min · jiezi

关于android:Fragment-可见性监听方案-完美兼容Android-x

我的公众号程序员徐公,四年中大厂工作教训,回复黑马,支付 Android 学习视频一份,回复徐公666,能够取得我精心整顿的简历模板,带你走近大厂。前言本篇文章次要提供一种监听 Fragment 可见性监听的计划,完满多种 case,有趣味的能够看看。废话不多说,开始进入注释。 在开发当中, fragment 常常应用到。在很多利用场景中,咱们须要监听到 fragment 的显示与暗藏,来进行一些操作。比方,统计页面的停留时长,页面暗藏的时候进行播放视频。 有些同学可能会说了,这还不容易,间接监听 Fragment 的 onResume,onPause。我只能说,兄弟,too young,too simple。 上面,让咱们一起来实现 fragment 的监听。次要分为几种 case 一个页面只有一个 fragment 的,应用 replaceHide 和 Show 操作ViewPager 嵌套 Fragment宿主 Fragment 再嵌套 Fragment,比方 ViewPager 嵌套 ViewPager,再嵌套 FragmentReplace 操作replace 操作这种比较简单,因为他会失常调用 onResume 和 onPause 办法,咱们只须要在 onResume 和 onPause 做 check 操作即可 override fun onResume() { info("onResume") super.onResume() onActivityVisibilityChanged(true) } override fun onPause() { info("onPause") super.onPause() onActivityVisibilityChanged(false) }Hide 和 Show 操作Hide 和 show 操作,会促发生命周期的回调,然而 hide 和 show 操作并不会,那么咱们能够通过什么办法来监听呢?其实很简略,能够通过 onHiddenChanged 办法 ...

February 19, 2023 · 6 min · jiezi

关于android:Android-初代-KV-存储框架-SharedPreferences旧时代的余晖

本文已收录到  AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。前言大家好,我是小彭。 SharedPreferences 是 Android 平台上轻量级的 K-V 存储框架,亦是初代 K-V 存储框架,至今被很多利用沿用。 有的小伙伴会说,SharedPreferences 是旧时代的产物,当初曾经有 DataStore 或 MMKV 等新时代的 K-V 框架,没有学习意义。但我认为,尽管 SharedPreference 这个计划曾经过期,然而并不意味着 SharedPreference 中应用的技术过期。做技术要知其然,更要知其所以然,而不是随声附和,如果要你解释为什么 SharedPreferences 会过期,你能说到什么水平? 不晓得你最近有没有读到一本在技术圈十分火爆的一本新书 《安卓传奇 · Android 缔造团队回忆录》,其中就讲了很多 Android 架构演进中设计者的思考。如果你平时也有从设计者的角度思考过 “为什么”,那么很多内容会感觉想到一块去了,反之就会感觉无感。 小彭的 Android 交换群 02 群曾经建设啦,公众号回复 “加群” 退出咱们~ —— 图片援用自电商平台 明天,咱们就来剖析 SharedPreference 源码,在过程中仍然能够学习到十分丰盛的设计技巧。在后续的文章中,咱们会持续剖析其余 K-V 存储框架,请关注。 本文源码剖析基于 Android 10(API 31),并关联剖析局部 Android 7.1(API 25)。 思维导图: 1. 实现 K-V 框架应该思考什么问题?在浏览 SharedPreference 的源码之前,咱们先思考一个 K-V 框架应该思考哪些问题? 问题 1 - 线程平安: 因为程序个别会在多线程环境中执行,因而框架有必要保障多线程并发平安,并且优化并发效率;问题 2 - 内存缓存: 因为磁盘 IO 操作是耗时操作,因而框架有必要在业务层和磁盘文件之间减少一层内存缓存;问题 3 - 事务: 因为磁盘 IO 操作是耗时操作,因而框架有必要将反对屡次磁盘 IO 操作聚合为一次磁盘写回事务,缩小拜访磁盘次数;问题 4 - 事务串行化: 因为程序可能由多个线程发动写回事务,因而框架有必要保障事务之间的事务串行化,防止先执行的事务笼罩后执行的事务;问题 5 - 异步写回: 因为磁盘 IO 是耗时操作,因而框架有必要反对后盾线程异步写回;问题 6 - 增量更新: 因为磁盘文件内容可能很大,因而批改 K-V 时有必要反对部分批改,而不是全量笼罩批改;问题 7 - 变更回调: 因为业务层可能有监听 K-V 变更的需要,因而框架有必要反对变更回调监听,并且防止出现内存透露;问题 8 - 多过程: 因为程序可能有多过程需要,那么框架如何保障多过程数据同步?问题 9 - 可用性: 因为程序运行中存在不可控的异样和 Crash,因而框架有必要尽可能保证系统可用性,尽量保证系统在遇到异样后的数据完整性;问题 10 - 高效性: 性能永远是要思考的问题,解析、读取、写入和序列化的性能如何进步和衡量;问题 11 - 安全性: 如果程序须要存储敏感数据,如何保障数据完整性和保密性;问题 12 - 数据迁徙: 如果我的项目中存在旧框架,如何将数据从旧框架迁徙至新框架,并且保障可靠性;问题 13 - 研发体验: 是否模板代码简短,是否容易出错。提出这么多问题后: ...

February 18, 2023 · 15 min · jiezi

关于android:RxJava-异常时堆栈显示不正确解决方法都在这里

本文首发我的博客,github 地址大家好,我是徐公,明天为大家带来的是 RxJava 的一个血案,一行代码 return null 引发的。 前阵子,组内的共事反馈说 RxJava 在 debug 包 crash 了,捕捉到的异样信息不全。(即咱们捕捉到的堆栈没有蕴含咱们本人代码,都是一些零碎或者 RxJava 框架的代码) 典型的一些 error 信息如下: 能够看到,下面的 Error 堆栈信息中,它并没有给出这个 Error 在理论我的项目中的调用门路。能够看到,报错的堆栈,提供的无效信息较少, 咱们只能晓得是因为 callable.call() 这里返回了 Null,导致出错。却不能判断 callable 是哪里创立的,这时候咱们只能联合日志上下文,判断以后之前的代码大略在哪里,再逐渐排查。 public final class ObservableFromCallable<T> extends Observable<T> implements Callable<T> { @Override public void subscribeActual(Observer<? super T> observer) { DeferredScalarDisposable<T> d = new DeferredScalarDisposable<T>(observer); observer.onSubscribe(d); if (d.isDisposed()) { return; } T value; try { // callable.call() 这里返回了 Null,并传递给了 RxJavaPlugins 的 errorHandler value = ObjectHelper.requireNonNull(callable.call(), "Callable returned null"); } catch (Throwable e) { Exceptions.throwIfFatal(e); if (!d.isDisposed()) { observer.onError(e); } else { RxJavaPlugins.onError(e); } return; } d.complete(value); }}一顿操作猛如虎,很多,咱们联合一些让下文日志,发现是这里返回了 null,导致出错 ...

February 17, 2023 · 4 min · jiezi

关于android:dex-优化编年史

本文作者:熊大引言在热修复和插件化场景中会波及动静加载 dex,要使它们中代码的执行速度与装置的 APK 相当,须要对它们进行正确的优化。依据以往的教训,在热修复场景中,谬误的形式导致 dex 没有失去优化时,修复后 App 的启动速度比修复前慢 50%。本文将在上面的局部介绍在 Android 5.0 以来的各零碎版本中对动静加载的 dex 进行优化的形式及原理。 Android 5从 Android 5.0 开始,零碎引入了事后编译机制(AOT),在利用装置时,应用 dex2oat 工具将 dex 编译为可执行文件。 此时能够通过 DexFile.loadDex 来触发 dex2oat 优化 dex,其调用过程如下: DexFile.loadDex -> new DexFile -> DexFile.openDexFile -> DexFile.openDexFileNative -> DexFile_openDexFileNative -> ClassLinker::OpenDexFilesFromOat -> ClassLinker::CreateOatFileForDexLocation -> ClassLinker::GenerateOatFile能够看到在 ClassLinker::GenerateOatFile 函数中会执行 dex2oat 命令来优化 dex。 // art/runtime/class_linker.cc(android-5.0.2)bool ClassLinker::GenerateOatFile(const char* dex_filename, int oat_fd, const char* oat_cache_filename, std::string* error_msg) { // ... std::vector<std::string> argv; argv.push_back(dex2oat); argv.push_back("--runtime-arg"); argv.push_back("-classpath"); argv.push_back("--runtime-arg"); argv.push_back(Runtime::Current()->GetClassPathString()); Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv); if (!Runtime::Current()->IsVerificationEnabled()) { argv.push_back("--compiler-filter=verify-none"); } if (Runtime::Current()->MustRelocateIfPossible()) { argv.push_back("--runtime-arg"); argv.push_back("-Xrelocate"); } else { argv.push_back("--runtime-arg"); argv.push_back("-Xnorelocate"); } if (!kIsTargetBuild) { argv.push_back("--host"); } argv.push_back(boot_image_option); argv.push_back(dex_file_option); argv.push_back(oat_fd_option); argv.push_back(oat_location_option); const std::vector<std::string>& compiler_options = Runtime::Current()->GetCompilerOptions(); for (size_t i = 0; i < compiler_options.size(); ++i) { argv.push_back(compiler_options[i].c_str()); } return Exec(argv, error_msg);}所以,可用 DexFile.loadDex 进行 dex 优化。 ...

February 17, 2023 · 7 min · jiezi

关于android:WebView-解决嵌套滑动冲突丝滑般实现吸顶效果完美兼容-X5-webview

本文首发我的微信公众号徐公,收录于 Github·AndroidGuide,这里有 Android 进阶成长常识体系, 心愿咱们可能一起学习提高,关注公众号徐公,5 年中大厂程序员,一起建设外围竞争力上一篇文章 【应用篇】WebView 实现嵌套滑动,丝滑般实现吸顶成果,完满兼容 X5 webview曾经解说了如何实现嵌套滑动,这篇文章,让咱们一起来看他的实现原理。废话不多说,开始进入注释。 前言解说之前,先简略说一下嵌套滑动的一些概念。(相熟这个的哥们能够间接跳过这个) 说到嵌套滑动,大家应该都不生疏。他是 Google 在 5.0 之后推出来的 NestedScroll 机制。 可能初学者会有这样的疑难?想比拟于传统的事件散发机制,NetstedScroll 机制有什么长处。 在传统的事件散发机制 中,一旦某个 View 或者 ViewGroup 生产了事件,就很难将事件交给父 View 进行独特解决。而 NestedScrolling 机制很好地帮忙咱们解决了这一问题。咱们只须要依照标准实现相应的接口即可,子 View 实现 NestedScrollingChild,父 View 实现 NestedScrollingParent ,通过 NestedScrollingChildHelper 或者 NestedScrollingParentHelper 实现交互。 如果对于 NestedScrolling 机制不理解的,能够看我几年前写的这篇文章。NestedScrolling 机制深刻解析 他联合 CoordinatorLayout 能够实现很多炫酷的成果,比方吸顶成果等。 有趣味的话能够看这些文章。 应用CoordinatorLayout打造各种炫酷的成果 自定义Behavior —— 仿知乎,FloatActionButton暗藏与展现 NestedScrolling 机制深刻解析 一步步带你读懂 CoordinatorLayout 源码 自定义 Behavior -仿新浪微博发现页的实现 ViewPager,ScrollView 嵌套ViewPager滑动抵触解决 自定义 behavior - 完满仿 QQ 浏览器首页,美团商家详情页 ...

February 17, 2023 · 4 min · jiezi

关于android:鲸鸿动能流量变现服务中国大陆地区测试流程

一、鲸鸿动能流量变现服务前置阐明1.接入鲸鸿动能平台的利用需在利用市场上架。 2.与华为联运的游戏利用和快游戏禁止接入鲸鸿动能以外的其余广告内容/插件/SDK等。 3.中国大陆地区仅反对企业认证用户应用流量变现服务。 4.反对的设施限度: 5.媒体接入流程: 二、媒体服务平台数据管理1) 【首页】或【我的报表】,反对查看预估收益以及广告展现数据。 2) 流量变现服务报表API,开发者能够通过调用报表API获取收益数据,包含申请量、返回量、点击率等。 媒体治理1) 增加媒体并填写材料。 2) 从利用市场获取SHA256指纹证书(大写)进行填写,如您后续在华为利用市场批改了证书指纹,请及时同步更新至SSP媒体治理后盾,免得影响广告交互链路。 展现位治理1) 展现位名称标准为“XX(利用残缺名称)XX场景XX款式”,例如:华为视频信息流大图。 2) 多个类似场景的地位可应用同一个展现位ID,倡议无需创立多个展现位ID。抉择展现位的模式和尺寸,填写 “展现位名称”,提交后即可集成自测。 广告尺寸抉择1) 极速广告 竖版利用图片反对10801620和10801920,倡议全选。 横版利用图片反对1920*1080。 2) 开屏广告  竖版利用图片反对10801620和10801920,倡议全选。  横版利用图片反对1920*1080。 3) Banner广告 Banner的主动刷新工夫距离,反对在媒体服务平台灵便设置【媒体治理-展现位】。 留神,横幅(Banner)广告有主动申请轮播机制,媒体平台中能够设置【默认刷新工夫60S,自定义刷新工夫,不刷新】。设置该展现位申请和展现新广告的工夫距离。若已应用SDK设置,则优先应用SDK中设置的刷新工夫。SDK中setBannerRefresh轮播工夫距离,单位:秒,取值范畴:[30, 120]。默认值:60秒。 4) 原生广告 利用/快利用的信息流场景,“原生”下可抉择图文1080607(举荐),225150(单图),225150(三图),7201280和10801620,视频可选640360。 图标场景在“原生”模式下抉择图片160*160。 5) 插屏广告 插屏视频反对640360、7201280和1280*720,倡议全选。 插屏场景的图片模式可应用“原生”创立并自渲染,尺寸抉择1080607;也可创立独立插屏款式,图片尺寸抉择10801920和1920*1080。 6) 激励视频广告 展现位反对视频格式,抉择640360和7201280两个尺寸,利于填充。 批改展现位1) 增加展现位后媒体状态是未启用,需提交验收,接入广告验收通过 并且上架利用市场,之后媒体状态会变更为启用。 2) 批改展现位 反对展现位类型、款式、尺寸规格从列表中选取,不反对自定义增加。 反对展现位格局和尺寸减少。 反对展现位格局和尺寸删减,但至多需保留一种款式和尺寸。 反对展现位状态的变更,启用或停用。 如需删除展现位,请为展现位名称加上“-废除”后停用,再删除。 华为验收通过后,将告诉您商业上架。此时需将测试ID替换为正式ID,将已接入华为广告的新版本公布到华为利用市场,利用市场审核通过后,分割华为经营配置广告,即可上线。 三、非中国大陆地区流量变现接入流程1、非中国大陆地区目前流量变现服务反对企业开发者或集体开发者的国家/地区(以帐号注册地为准)。 2、注册地为中国大陆的出海开发者,不倡议应用Smart Banner性能。因为Smart Banner广告在中国大陆区域暂未反对(鲸鸿动能广告媒体服务平台界面无奈抉择非中国大陆可反对规格尺寸),应用Smart Banner会导致在非中国大陆区域申请不到广告。 非中国大陆地区流量变现流程: 注:广告有三个投放站点,不反对跨站点获取广告资源。广告站点别离是:俄罗斯,亚非拉,欧洲。 3、测试环境 测试环境需满足以下条件,否则有可能存在申请不到广告的状况: ...

February 16, 2023 · 1 min · jiezi

关于android:如何在现实场景中随心放置AR虚拟对象

随着AR的倒退和电子设备的遍及,人们在生活中应用AR技术的门槛升高,比方对于不不便测量的物体应用AR测量,不便又精确;遇到生疏的路段应用AR导航,分明又便捷;网购时拿不准的物品应用AR购物,体验更真切。 想要让虚构物体和事实世界相交融,重要的一步就是将虚构对象精确搁置在事实场景中,当用户触摸电子屏幕上的任意中央时即可创立AR对象,达到良好的交互体验。 华为HMS Core AR Engine继续跟踪设施绝对于周围环境的地位和姿势变动轨迹,建设虚构数字世界和事实物理世界的对立几何空间,为您的利用提供虚实交融的交互根底平台。其中命中检测技术让用户可通过点击终端设备屏幕选中事实环境中的趣味点,终端设备屏幕上的趣味点映射为事实环境中的趣味点,并以趣味点为源收回一条射线连贯到摄像头所在位置,返回这条射线贯通的任何立体或特色点以及穿插地位在事实世界空间中的地位和姿势。命中检测与立体碰撞,取得碰撞点的地位及法向量,让用户能够自由选择环境中的物体或者与它们互动。 Demo 开发步骤开发环境要求: JDK 1.8.211及以上。 装置Android Studio 3.0及以上: minSdkVersion 26及以上 targetSdkVersion 29(举荐) compileSdkVersion 29(举荐) Gradle 6.1.1及以上(举荐) 在华为终端设备上的利用市场下载AR Engine服务端APK(需在华为利用市场,搜寻“华为AR Engine”)并装置到终端设备。 测试利用的设施:参见AREngine个性软硬件依赖表中环境Mesh反对设施列表。如果同时应用多个HMS Core的服务,则须要应用各个Kit对应的最大值。 开发筹备在开发利用前须要在华为开发者联盟网站上注册成为开发者并实现实名认证,具体方法请参见帐号注册认证。华为提供了Maven仓集成形式的AR Engine SDK包,在开始开发前,须要将AR Engine SDK集成到您的开发环境中。Android Studio的代码库配置在Gradle插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请依据您以后的Gradle插件版本,抉择对应的配置过程。以7.0为例:关上Android Studio我的项目级“build.gradle”文件,增加Maven代码库。 在“buildscript > repositories”中配置HMS Core SDK的Maven仓地址。 buildscript { repositories { google() jcenter() maven {url "https://developer.huawei.com/repo/" } }}关上我的项目级“settings.gradle”文件,配置HMS Core SDK的Maven仓地址 dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { repositories { google() jcenter() maven {url "https://developer.huawei.com/repo/" } } }}增加依赖 在“dependencies”中增加如下编译依赖:dependencies { implementation 'com.huawei.hms:arenginesdk:{version}}开发步骤首先创立WorldRenderManager,这个类提供了与世界场景相干的渲染治理,包含标签渲染和虚构对象渲染治理。public class WorldRenderManager implementsGLSurfaceView.Renderer{ //此办法构造函数传递上下文 public WorldRenderManager(Activity activity, Context context) { mActivity = activity; mContext = context; …}//此办法设置ARSession,它将更新并获取OnDrawFrame中的最新数据。public void setArSession(ARSession arSession) { if (arSession == null) { LogUtil.error(TAG, "setSession error, arSession is null!"); return; } mSession = arSession; }//设置ARWorldTrackingConfig,获取配置模式。public void setArWorldTrackingConfig(ARWorldTrackingConfig arConfig) { if (arConfig == null) {LogUtil.error(TAG, "setArWorldTrackingConfig error, arConfig is null!"); return; } mArWorldTrackingConfig = arConfig; }//实现onDrawFrame办法@Overridepublic void onDrawFrame(GL10 unused) { mSession.setCameraTextureName(mTextureDisplay.getExternalTextureId());ARFrame arFrame = mSession.update();ARCamera arCamera = arFrame.getCamera();…….}//命中后果输入private ARHitResult hitTest4Result(ARFrame frame, ARCamera camera, MotionEvent event) { ARHitResult hitResult = null; List<ARHitResult> hitTestResults = frame.hitTest(event);//确定命中点是否在立体多边形内。ARHitResult hitResultTemp = hitTestResults.get(i); if (hitResultTemp == null) { continue; }ARTrackable trackable = hitResultTemp.getTrackable(); //确定点云是否被单击,以及点是否面向相机。 boolean isPointHitJudge = trackable instanceof ARPoint&& ((ARPoint) trackable).getOrientationMode() == ARPoint.OrientationMode.ESTIMATED_SURFACE_NORMAL;//优先选择立体上的点。if (isPlanHitJudge || isPointHitJudge) { hitResult = hitResultTemp; if (trackable instanceof ARPlane) { break; } }return hitResult;}}创立WorldActivity,本AR示例介绍了如何应用HUAWEI AR Engine的世界AR场景。public class WorldActivity extends BaseActivity { private ARSession mArSession;private GLSurfaceView mSurfaceView;private ARWorldTrackingConfig mConfig;@Overrideprotected void onCreate(Bundle savedInstanceState) { LogUtil.info(TAG, "onCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.world_java_activity_main); mWorldRenderManager = new WorldRenderManager(this, this);mWorldRenderManager.setDisplayRotationManage(mDisplayRotationManager);mWorldRenderManager.setQueuedSingleTaps(mQueuedSingleTaps) }@Overrideprotected void onResume() { if (!PermissionManager.hasPermission(this)) { this.finish(); } errorMessage = null; if (mArSession == null) { try { if (!arEngineAbilityCheck()) { finish(); return; } mArSession = new ARSession(this.getApplicationContext()); mConfig = new ARWorldTrackingConfig(mArSession); refreshConfig(ARConfigBase.LIGHT_MODE_ENVIRONMENT_LIGHTING | ARConfigBase.LIGHT_MODE_ENVIRONMENT_TEXTURE); } catch (Exception capturedException) { setMessageWhenError(capturedException); } if (errorMessage != null) { stopArSession(); return; }}@Override protected void onPause() { LogUtil.info(TAG, "onPause start."); super.onPause(); if (mArSession != null) { mDisplayRotationManager.unregisterDisplayListener(); mSurfaceView.onPause(); mArSession.pause(); } LogUtil.info(TAG, "onPause end."); }@Override protected void onDestroy() { LogUtil.info(TAG, "onDestroy start."); if (mArSession != null) { mArSession.stop(); mArSession = null; } if (mWorldRenderManager != null) { mWorldRenderManager.releaseARAnchor(); } super.onDestroy(); LogUtil.info(TAG, "onDestroy end."); }…..}理解更多详情>> ...

February 15, 2023 · 2 min · jiezi

关于android:AndroidANR入门学习笔记

「Android」ANR入门学习笔记ANR 全称是 Applicatipon Not Response ,Android 设计 ANR 的用意,是零碎通过与之交互的组件以及用户交互进行超时监控,用来判断利用过程是否存在卡死或响应过慢的问题 ANR 的触发起因应用层导致 ANR 的起因: 函数阻塞:如死循环、主线程 IO、解决大数据锁出错:主线程期待子线程的锁内存缓和:零碎调配给一个利用的内存是有下限的,长期处于内存缓和,会导致频繁内存替换,进而导致利用的一些操作超时零碎导致ANR 的起因: CPU 被抢占:一般来说,前台在玩游戏,可能会导致你的后盾播送被抢占零碎服务无奈及时响应:比方获取零碎联系人等,零碎的服务都是 Binder 机制,服务能力也是无限的,有可能零碎服务长时间不响应导致 ANR其余利用占用大量内存ANR 的触发规范简略来说,ANR 就是零碎响应超时,Android对于零碎是否响应超时有如下规范: Service 触发ANR Service Timeout:比方前台服务在20s内未执行实现,后盾服务 Timeout 工夫是前台服务的10倍,200s;Broadcast 触发ANR BroadcastQueue Timeout:比方前台播送在10s内未执行实现,后盾60s;Provider 触发ANR ContentProvider Timeout:内容提供者,在 publish 过超时10s;Input 触发ANR InputDispatching Timeout:输出事件散发超时5s,包含按键和触摸事件。//ActiveServices.java// How long we wait for a service to finish executing.static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;// How long the startForegroundService() grace period is to get around to// calling startForeground() before we ANR + stop it.static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000;//ActivityManagerService.java// How long we allow a receiver to run before giving up on it.static final int BROADCAST_FG_TIMEOUT = 10*1000;static final int BROADCAST_BG_TIMEOUT = 60*1000;// How long we wait until we timeout on key dispatching.static final int KEY_DISPATCHING_TIMEOUT = 5*1000;ANR 的触发流程对于Service、Broadcast、Provider触发的ANR来说,相似于是一个埋炸弹、拆炸弹、引爆炸弹的过程,例如startService的时候: ...

February 14, 2023 · 10 min · jiezi

关于android:vivo官网App模块化开发方案ModularDevTool

作者:vivo 互联网客户端团队- Wang Zhenyu本文次要讲述了Android客户端模块化开发的痛点及解决方案,具体解说了计划的实现思路和具体实现办法。 阐明:本工具基于vivo互联网客户端团队外部开源的编译管理工具开发。一、背景当初客户端的业务越来越多,大部分客户端工程都采纳模块化的开发模式,也就是依据业务分成多个模块进行开发,进步团队效率。例如咱们vivo官网当初的整体架构如下图,分为13个模块,每个模块是一个独立代码仓。 (注:为什么这么分,能够参考之前的一篇文章《Android模块化开发实际》) 二、痛点齐全隔离的代码仓,使每个模块更独立,更易于代码治理,但也带来了一些问题。 1、开发阶段,子仓开发以及集成开发调试,操作麻烦、易出错、难跟踪回溯 1.1、当开发时波及的模块较多时,须要手动一个一个拉代码,多个子仓的代码操作十分麻烦,并且须要关上多个AndroidStudio进行开发; 1.2、子仓集成到主仓开发调试,有两种形式,然而都有比拟大的毛病: (1)形式1,子仓通过maven依赖,这种形式须要一直的公布子仓的snapshot,主仓再更新snapshot,效率较低; (2)形式2,子仓通过代码依赖,也就是须要在主仓的settings.gradle中,手动include拉到本地的子仓代码,而后在build.gradle中配置dependencies,配置繁琐,容易出错; 1.3、主仓对子仓的依赖,如果是局部maven依赖、局部代码依赖,容易呈现代码抵触; 1.4、apk集成的子模块aar和代码,没有对应关系,排查问题时很难回溯。 2、版本公布阶段,流程繁琐,过多重复劳动,流程如下: 2.1、一一批改子仓的版本,指定snapshot或release; 2.2、每个子仓须要提交批改版本号的代码到git; 2.3、每个子仓都要手动触发公布maven仓; 2.4、更新主仓对子仓依赖的版本; 2.5、构建Apk; 2.6、如果用继续集成系统CI,则每个子仓都须要配置一个我的项目,再一一启动子仓的编译,等子仓全副编译完再启动主仓编译。 三、计划针对上述问题,咱们优化的思路也很明确了,就是以自动化的形式解决繁琐和反复的操作。最终开发了ModularDevTool,实现以下性能: 1、开发阶段 1.1、在主仓中,治理所有子仓代码(拉代码、切分支及其他git操作),治理子仓相干信息(代码仓门路、分支、版本等); 1.2、只须要关上一个AS工程,即可进行所有仓的代码开发; 1.3、对子仓的两种依赖形式(代码依赖和maven依赖)一键切换,反对混合依赖(即局部仓代码依赖,局部仓maven依赖); 1.4、编译时输入子模块的版本及对应commitid,便于回溯跟踪代码。 2、版本公布阶段 2.1、只须要在主仓批改子仓版本号,子仓无需批改,省去子仓代码批改和提交代码过程; 2.2、CI上只有配一个主仓我的项目,实现一键编译,包含子仓编译aar(按依赖关系程序编译)、上传maven、编apk; 2.3、CI上反对3种编译模式: OnlyApp:即只编译主仓代码生成apk(前提是子模块已公布maven);publishSnapshot:即子仓编译上传snapshot版本,而后编译主仓生成apk;publishRelease:即子仓编译上传release版本,而后编译主仓生成apk。四、ModularDevTool概览工具采纳了shell脚本+gradle插件的形式实现的。 首先看下工程目录概览 1、submodules目录是用来寄存子仓代码的,子仓代码就是失常的工程构造,submodules目录如下图: 2、repositories.xml文件是用来配置子仓信息的,包含模块名、代码仓、分支、版本等,具体内容如下: <?xml version="1.0" encoding="utf-8" ?><repositories> <!-- 一个repository示意一个仓库,一个仓库下可能会有多个module --> <repository> <!-- 仓库名称,能够随便定义,次要用于本地疾速辨认 --> <name>lib模块</name> <!-- 上传至maven时的groupid --> <group>com.vivo.space.lib</group> <!-- 配置仓库中的所有子模块,如果多个module就增加多个module标签 --> <modules> <module> <!-- 上传至maven时的artifactid --> <artifactid>vivospace_lib</artifactid> <!-- 上传至maven时的版本号 --> <version>5.9.8.0-SNAPSHOT</version> <!-- 编译程序优先级,越小优先级越高 --> <priority>0</priority> </module> </modules> <!-- 留神仓库地址中的集体ssh名称要应用$user占位符代替 --> <repo>ssh://$user@smartgit:xxxx/VivoCode/xxxx_lib</repo> <!-- 开发分支,脚本用来主动切换到该分支 --> <devbranch>feature_5.9.0.0_xxx_dev</devbranch> <!-- 打release包时必须强制指定commitId,保障取到指定代码 --> <commitid>cbd4xxxxxx69d1</commitid> </repository> <!-- 多个仓库就增加多个repository --> ...</repositories>3、vsub.sh脚本是工具各种性能的入口,比方: ...

February 14, 2023 · 2 min · jiezi

关于android:抓取安卓闪退日志教程

在开发手机APP时,如果遇到利用闪退、卡顿无反馈状况,往往须要抓取日志,帮忙定位问题。本文简要介绍应用adb抓取日志的办法。 分以下三步进行介绍:1. 装置java 运行环境 jdk, 并配置java环境变量;2. 装置Android Studio,配置环境变量 ;3. 应用adb命令。 一:装置java 运行环境 jdk, 并配置java环境变量。1.1 下载JDK  下载地址:https://www.oracle.com/java/technologies/downloads/#jdk19-windows 1.2 下载后双击安装包进行装置。 1.3 装置实现后,配置Java 环境变量。 在windows底部任何栏关上搜寻图标,搜寻环境变量,关上编辑零碎环境变量面板,: 在零碎变量面板,新建JAVA_HOME环境变量,并配置值为JDK装置门路: 新建一个CLASSPATH变量,值为: .;%JAVA\_HOME%\lib;%JAVA\_HOME%\lib\tools.jar;%JAVA\_HOME%\jre\lib\rt.jar;%JAVA\_HOME%\lib\dt.jar 配置零碎的path变量 最初一步了,找到path变量,编辑,新增两个值 %JAVA\_HOME%\bin   %JAVA\_HOME%\jre\bin  如下图: 1.4 测验java环境变量配置是否胜利。 Win+r ,输出cmd 关上命令行, 输出javac 呈现如下图所示即可表明JDK变量配置胜利。 二,装置Android Studio,配置环境变量。     2.1  下载Android Studio 并装置。下载地址:https://developer.android.google.cn/studio/      2.2 在零碎变量中新建 Android_Home ,  输出两个值,    C:\Users\Dell\AppData\Local\Android\Sdk     C:\Users\Dell\AppData\Local\Android\platform-tools 如下图: 三、 应用adb命令。3.1  手机关上USB调试模式。应用数据线连贯电脑和手机。手机上弹出框,抉择文件传输。 3.2  在命令行中输出 adb devices , 连贯设施 ...

February 13, 2023 · 1 min · jiezi

关于android:原理篇WebView-实现嵌套滑动丝滑般实现吸顶效果完美兼容-X5-webview

本文首发我的微信公众号徐公,收录于 Github·AndroidGuide,这里有 Android 进阶成长常识体系, 心愿咱们可能一起学习提高,关注公众号徐公,5 年中大厂程序员,一起建设外围竞争力上一篇文章 【应用篇】WebView 实现嵌套滑动,丝滑般实现吸顶成果,完满兼容 X5 webview曾经解说了如何实现嵌套滑动,这篇文章,让咱们一起来看他的实现原理。废话不多说,开始进入注释。 前言解说之前,先简略说一下嵌套滑动的一些概念。(相熟这个的哥们能够间接跳过这个) 说到嵌套滑动,大家应该都不生疏。他是 Google 在 5.0 之后推出来的 NestedScroll 机制。 可能初学者会有这样的疑难?想比拟于传统的事件散发机制,NetstedScroll 机制有什么长处。 在传统的事件散发机制 中,一旦某个 View 或者 ViewGroup 生产了事件,就很难将事件交给父 View 进行独特解决。而 NestedScrolling 机制很好地帮忙咱们解决了这一问题。咱们只须要依照标准实现相应的接口即可,子 View 实现 NestedScrollingChild,父 View 实现 NestedScrollingParent ,通过 NestedScrollingChildHelper 或者 NestedScrollingParentHelper 实现交互。 如果对于 NestedScrolling 机制不理解的,能够看我几年前写的这篇文章。NestedScrolling 机制深刻解析 他联合 CoordinatorLayout 能够实现很多炫酷的成果,比方吸顶成果等。 有趣味的话能够看这些文章。 应用CoordinatorLayout打造各种炫酷的成果 自定义Behavior —— 仿知乎,FloatActionButton暗藏与展现 NestedScrolling 机制深刻解析 一步步带你读懂 CoordinatorLayout 源码 自定义 Behavior -仿新浪微博发现页的实现 ViewPager,ScrollView 嵌套ViewPager滑动抵触解决 自定义 behavior - 完满仿 QQ 浏览器首页,美团商家详情页 ...

February 13, 2023 · 4 min · jiezi

关于android:Android-IO-框架-Okio-的实现原理如何检测超时

本文已收录到  AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。前言大家好,我是小彭。 在上一篇文章里,咱们聊到了 Square 开源的 I/O 框架 Okio 的三个劣势:精简且全面的 API、基于共享的缓冲区设计以及超时机制。前两个劣势曾经剖析过了,明天咱们来剖析 Okio 的超时检测机制。 本文源码基于 Okio v3.2.0。 思维导图: 1. 意识 Okio 的超时机制超时机制是一项通用的零碎设计,可能防止零碎长时间阻塞在某些工作上。例如网络申请在超时工夫内没有响应,客户端就会提前中断请求,并提醒用户某些性能不可用。 1.1 说一下 Okio 超时机制的劣势先思考一个问题,相比于传统 IO 的超时有什么劣势呢?我认为次要体现在 2 个方面: 劣势 1 - Okio 补救了局部 IO 操作不反对超时检测的缺点:Java 原生 IO 操作是否反对超时,齐全取决于底层的零碎调用是否反对。例如,网络 Socket 反对通过 setSoTimeout API 设置单次 IO 操作的超时工夫,而文件 IO 操作就不反对,应用原生文件 IO 就无奈实现超时。 而 Okio 是对立在应用层实现超时检测,不论零碎调用是否反对超时,都能提供对立的超时检测机制。 劣势 2 - Okio 不仅反对单次 IO 操作的超时检测,还反对蕴含屡次 IO 操作的复合工作超时检测:Java 原生 IO 操作只能实现对单次 IO 操作的超时检测,无奈实现对蕴含屡次 IO 操作的复合工作超时检测。例如,OkHttp 反对配置单次 connect、read 或 write 操作的超时检测,还反对对一次残缺 Call 申请的超时检测,有时候单个操作没有超时,但串联起来的残缺 call 却超时了。 ...

February 11, 2023 · 7 min · jiezi

关于android:Android-IO-框架-Okio-的实现原理到底哪里-OK

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。前言大家好,我是小彭。 明天,咱们来探讨一个 Square 开源的 I/O 框架 Okio,咱们最开始接触到 Okio 框架还是源于 Square 家的 OkHttp 网络框架。那么,OkHttp 为什么要应用 Okio,它相比于 Java 原生 IO 有什么区别和劣势?明天咱们就围绕这些问题开展。 本文源码基于 Okio v3.2.0。 思维导图 1. 说一下 Okio 的劣势?相比于 Java 原生 IO 框架,我认为 Okio 的劣势次要体现在 3 个方面: 1、精简且全面的 API: 原生 IO 应用装璜模式,例如应用 BufferedInputStream 装璜 FileInputStream 文件输出流,能够加强流的缓冲性能。然而原生 IO 的装璜器过于宏大,须要辨别字节、字符流、字节数组、字符数组、缓冲等多种装璜器,而这些恰好又是最罕用的根底装璜器。相较之下,Okio 间接在 BufferedSource 和 BufferedSink 中聚合了原生 IO 中所有根底的装璜器,使得框架更加精简;2、基于共享的缓冲区设计: 因为 IO 零碎调用存在上下文切换的性能损耗,为了缩小零碎调用次数,应用层往往会采纳缓冲区策略。然而缓冲区又会存在副作用,当数据从一个缓冲区转移到另一个缓冲区时须要拷贝数据,这种内存中的拷贝显得没有必要。而 Okio 采纳了基于共享的缓冲区设计,在缓冲区间转移数据只是共享 Segment 的援用,而缩小了内存拷贝。同时 Segment 也采纳了对象池设计,缩小了内存调配和回收的开销;3、超时机制: Okio 补救了局部 IO 操作不反对超时检测的缺点,而且 Okio 不仅反对单次 IO 操作的超时检测,还反对蕴含屡次 IO 操作的复合工作超时检测。上面,咱们将从这三个劣势开展剖析: ...

February 10, 2023 · 7 min · jiezi

关于android:YonBuilder移动开发平台App拉起第三方应用

在App的开发过程中,有一种常见场景,就是拉起第三方app,那么应用YonBuilder挪动开发做app的时候,是怎么拉起第三方App的呢,下边咱们讲一下步骤。咱们以安卓利用关上支付宝为例进行阐明:首先咱们在YonBuilder挪动开发中,找到端设置界面;点击编辑能够增加支付宝,包名也是默认增加上的;编辑实现之后保留,批改通用配置后须要从新编译一下;通用配置里边蕴含了常见利用,如果里边没有须要本人查找利用的包名进行配置;而后,咱们就能够在代码中调用关上第三方利用的办法了, 办法具体可参考YonBuilder挪动开发平台开发者文档:https://developer.yonyou.com/...示例代码如下: api.openApp({ androidPkg: 'android.intent.action.VIEW', mimeType: 'text/html', uri: 'http://www.baidu.com' }, function (ret, err) { if (ret) { api.alert({ msg: JSON.stringify(ret) }); } else { api.alert({ msg: JSON.stringify(err) }); } });这样咱们就能够通过调用api.openApp关上第三方利用了,关上支付宝首页的示例代码 api.openApp({ androidPkg: 'com.eg.android.AlipayGphone', uri: 'alipay://'}, function (ret, err) {});效果图如下:点击按钮后调用api.openApp办法能够跳转到支付宝:关上第三方利用的时候也反对传参数,具体能够看开发者文档的appParam参数介绍,依据本人的需要灵便利用;

February 9, 2023 · 1 min · jiezi

关于android:ThreadLocal-超强图解这次终于懂了

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 发问。前言大家好,我是小彭。 在后面的文章里,咱们聊到了散列表的凋谢寻址法和拆散链表法,也聊到了 HashMap、LinkedHashMap 和 WeakHashMap 等基于拆散链表法实现的散列表。 明天,咱们来探讨 Java 规范库中一个应用凋谢寻址法的散列表构造,也是 Java & Android “面试八股文” 的规范题库之一 —— ThreadLocal。 本文源码基于 Java 8 ThreadLocal。 思维导图: 1. 回顾散列表的工作原理在开始剖析 ThreadLocal 的实现原理之前,咱们先回顾散列表的工作原理。 散列表是基于散列思维实现的 Map 数据结构,将散列思维利用到散列表数据结构时,就是通过 hash 函数提取键(Key)的特征值(散列值),再将键值对映射到固定的数组下标中,利用数组反对随机拜访的个性,实现 O(1) 工夫的存储和查问操作。 散列表示意图 在从键值对映射到数组下标的过程中,散列表会存在 2 次散列抵触: 第 1 次 - hash 函数的散列抵触: 这是个别意义上的散列抵触;第 2 次 - 散列值取余转数组下标: 实质上,将散列值转数组下标也是一次 Hash 算法,也会存在散列抵触。事实上,因为散列表是压缩映射,所以咱们无奈防止散列抵触,只能保障散列表不会因为散列抵触而失去正确性。罕用的散列抵触解决办法有 2 类: 凋谢寻址法: 例如 ThreadLocalMap;拆散链表法: 例如 HashMap。凋谢寻址(Open Addressing)的核心思想是: 在呈现散列抵触时,在数组上从新探测出一个闲暇地位。 经典的探测办法有线性探测、平方探测和双散列探测。线性探测是最根本的探测办法,咱们明天要剖析的 ThreadLocal 中的 ThreadLocalMap 散列表就是采纳线性探测的凋谢寻址法。 ...

February 8, 2023 · 12 min · jiezi

关于android:Androidbuildgradle中的implementation和api

「Android」build.gradle中的implementation和api在 gradle 3.0 之后,默认的依赖由之前的 compile 更新为 implementation 和 api 。 区别而 implementation 和 api 之间的区别,次要是: implementation :该依赖形式所依赖的库不会传递。这种依赖关系,当其余module依赖该module时,无奈应用该module下应用 implementation 所依赖的库 api :该依赖形式所依赖的库会传递。这种依赖关系,当其余module依赖该module时,能够应用该module下应用 api 所依赖的库举例假如module A依赖module B( implementation 和 api 都能够): 若 B implementation C :A无奈调用C若 B api C :A能够调用C

February 8, 2023 · 1 min · jiezi

关于android:AndroidIdleHandler详解

「Android」IdleHandler入门based on Android API 28IdleHandler,这是一种在只有当音讯队列没有音讯时或者是队列中的音讯还没有到执行工夫时才会执行的 IdleHandler,它寄存在 mPendingIdleHandlers 队列中。 /** * Callback interface for discovering when a thread is going to block * waiting for more messages. */ public static interface IdleHandler { /** * Called when the message queue has run out of messages and will now wait for more. * Return true to keep your idle handler active, false to have it removed. * 返回 true,则放弃该回调;返回 false,则移除该回调 * This may be called if there are still messages pending in the queue, * but they are all scheduled to be dispatched after the current time. */ boolean queueIdle(); }依据正文可知:IdleHandler 是一个回调接口,当线程中的音讯队列将要阻塞期待音讯的时候,就会回调该接口,也就是说音讯队列中的音讯都处理完毕了,没有新的音讯了,处于闲暇状态时就会回调该接口。 ...

February 8, 2023 · 5 min · jiezi

关于android:全新Mac安装STF全记录

STF 介绍STF是一个挪动设施群控计划的开源实现,原名是 OpenSTF,由 CyberAgent, HeadSpin 以及其余贡献者等反对。起初就由device farm接手了,并改名为 @devicefarmer/stf 装置环境硬件: Mac Air M1芯片操作系统版本:Mac Ventura装置步骤应用app store 装置xcode装置brew拜访 https://brew.sh/ 装置,即 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"装置npm先装置nvm,而后装置node 8.9.1版本 brew install nvmnvm install 8.9.1brew install python3装置stf依照 https://github.com/DeviceFarm... 提供的指引装置, brew install rethinkdb graphicsmagick zeromq protobuf yasm pkg-config cmakenpm install -g @devicefarmer/stf --python=python2.7最开始是执行以下命令装置@devicefarmer/stf的, npm install -g @devicefarmer/stf然而报错了 Python executable "python" is v3.9.6, which is not supported by gyp前面通过排查,有人说要加--python=python2.7参数 碰到的其余问题xcode-select: errorxcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance解决办法: ...

February 7, 2023 · 1 min · jiezi

关于android:AR-Engine毫秒级平面检测带来更准确的呈现效果

近年来,AR版块成为时下大热,这是一种将事实环境中不存在的虚构物体交融到实在环境里的技术,用户借助显示设施能够领有实在的感官体验。AR的利用场景非常宽泛,波及娱乐、社交、广告、购物、教育等畛域:AR能够让游戏更具互动性;商品通过AR展现更实在;应用AR进行教育教学让形象事物更形象等,能够说AR技术曾经浸透人们生存的方方面面。 为了让人们产生强烈的视觉真实感,AR首先要解决的问题就是如何将虚构对象精确地交融到事实世界中,即让虚构对象以正确的姿势显示在实在场景的正确地位上。一些AR计划实现环境辨认与摄像机位姿计算之后,没有进行立体检测就间接叠加虚构对象显示,导致虚构对象与实在环境没有很好的贴合度,用户容易产生视觉错位,影响虚构对象在事实中的出现成果。因而,如何在不同的实在环境中精确检测出程度或垂直立体,与搁置虚构对象地位的立体保持一致,是用户与AR进行交互的重要一步。 华为HMS Core AR Engine跟踪设施四周的光照、立体、图像、物体、环境外表等环境信息,辅助开发者们的利用实现虚构物体以场景化的形式真切地融入事实物理世界。其中立体检测能力可辨认到程度和垂直立体(高空或墙面)上的成群特色点,并可辨认到立体的边界,开发者们的利用可应用这些立体来搁置须要的虚构物体。 Demo 性能特点反对辨认程度立体、垂直立体辨认 准确度2.5cm@1m 辨认失常纹理速度<1s 反对多边形拟合和立体合并 开发步骤开发环境要求:JDK 1.8.211及以上。 装置Android Studio 3.0及以上: minSdkVersion 26及以上 targetSdkVersion 29(举荐) compileSdkVersion 29(举荐) Gradle 6.1.1及以上(举荐) 在华为终端设备上的利用市场下载AR Engine服务端APK(需在华为利用市场,搜寻“华为AR Engine”)并装置到终端设备。 测试利用的设施:参见AREngine个性软硬件依赖表中环境Mesh反对设施列表。如果同时应用多个HMS Core的服务,则须要应用各个Kit对应的最大值。 开发筹备在开发利用前须要在华为开发者联盟网站上注册成为开发者并实现实名认证,具体方法请参见帐号注册认证。华为提供了Maven仓集成形式的AR Engine SDK包,在开始开发前,须要将AR Engine SDK集成到您的开发环境中。Android Studio的代码库配置在Gradle插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请依据您以后的Gradle插件版本,抉择对应的配置过程。以7.0为例:关上Android Studio我的项目级“build.gradle”文件,增加Maven代码库。 在“buildscript > repositories”中配置HMS Core SDK的Maven仓地址。 buildscript { repositories { google() jcenter() maven {url "https://developer.huawei.com/repo/" } }}关上我的项目级“settings.gradle”文件,配置HMS Core SDK的Maven仓地址 dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { repositories { google() jcenter() maven {url "https://developer.huawei.com/repo/" } } }}增加依赖 在“dependencies”中增加如下编译依赖:dependencies { implementation 'com.huawei.hms:arenginesdk:{version}}开发步骤首先创立WorldActivity,这个Activity介绍如何应用HUAWEI AR Engine的世界AR场景。Public class WorldActivity extends BaseActivity{Protected void onCreate(Bundle saveInstanceState){ 初始化DisplayRotationManager mDisplayRotationManager = new DisplayRotationManager(this); 初始化WorldRenderManager mWorldRenderManager = new WorldRenderManager(this,this);} //写一个手势处理器 Private void initGestureDetector(){mGestureDetector = new GestureDetector(this,new GestureDetector.SimpleOnGestureListener()){ } } mSurfaceView.setOnTouchListener(new View.OnTouchListener()){ public Boolean onTouch(View v,MotionEvent event){ return mGestureDetector.onTouchEvent(event); } } //在onResume生命周期中创立ARWorldTrackingConfig protected void onResume(){ mArSession = new ARSession(this.getApplicationContext()); mConfig = new ARWorldTrackingConfig(mArSession); …}//创立刷新配置类private void refreshConfig(int lightingMode){ //设置对焦 mConfig.setFocusMode(ARConfigBase.FocusMode.AUTO_FOCUS); mArSession.configure(mConfig);}}创立WorldRenderManager类,该类提供与世界场景相干的渲染治理,包含标签渲染和虚构对象渲染治理。public class WorldRenderManager implements GLSurfaceView.Renderr{ //须要创立一个绘制框架的类 Public void onDrawFrame(GL10 unused){ //设置可用于存储相机预览流数据的openGL textureIdmSession.setCameraTextureName(mTextureDisplay.getExternalTextureId());//更新AR Engine的计算结果,利用应在须要获取最新的数据时调用此接口ARFrame arFrame = mSession.update();//获取以后帧的相机参数。ARCamera arCamera = arFrame.getCamera();//返回一个坐标运算相干的投影矩阵,可用于相机坐标系到裁剪坐标系转换。arCamera.getProjectionMatrix(projectionMatrix, PROJ_MATRIX_OFFSET, PROJ_MATRIX_NEAR, PROJ_MATRIX_FAR);Session.getAllTrackables(ARPlane.class)….. }}创立VirtualObject类,该类提供虚构对象的属性以及与虚构对象渲染相干的必要办法。Public class VirtualObject{}创立ObjectDisplay类,依据指定的参数绘制虚构对象。Public class ObjectDisplay{}理解更多详情>> ...

February 6, 2023 · 1 min · jiezi

关于android:数据结构Hash常见操作实践

数据结构-Hash常见操作实际目录介绍01.什么是哈希算法02.哈希算法的利用03.平安加密的场景04.惟一标识的场景05.数据校验的场景06.散列函数的场景07.Git版本的管制08.云存储文件场景09.哈希算法的总结10.哈希算法的特点11.哈希算法的实际12.罕用哈希码算法13.Map哈希的算法14.了解HashCode15.哈希抵触的解决16.问题思考的答疑01.什么是哈希算法哈希算法历史悠久 业界驰名的哈希算法也很多,比方MD5、SHA等。在平时的开发中,基本上都是拿现成的间接用。明天不会重点分析哈希算法的原理,也不会教你如何设计一个哈希算法,而是从实战角度通知你,在理论开发中,咱们该如何用哈希算法解决问题。什么是哈希算法,用一句话就能够概括了。 将任意长度的二进制值串映射为固定长度的二进制值串,这个映射规定就是哈希算法,而通过原始数据映射之后失去的二进制值串就是哈希值。然而,要设计一个优良的哈希算法并不容易,我了须要满足的几点要求: 从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希算法);对输出数据十分敏感,哪怕原始数据只批改了一个Bit,最初失去的哈希值也大不相同;散列总被的概率要很小,对于不同的原始数据,哈希值雷同的概率十分小;哈希算法的执行效率尽量高效,针对较长的文本,也能疾速计算出哈希值。拿MD5这种哈希算法具体阐明下,比方计算这两个文本的MD5哈希值——“明天我来讲哈希算法”、“jiajia"。失去的两串毫无法则的字符串(MD5的哈希值是128位的Bit长度,便于示意,转化为16进制编码)。能够看出,无论文本的长度是多少,失去的哈希值长度是雷同的,而且看起来像一堆随机数,齐全没有法则。 MD5("明天我来讲哈希算法") = bb4767201ad42c74e650c1b6c03d78faMD5("jiajia") = cd611a31ea969b908932d44d126d195b试试两个很类似的文本,尽管只有一个标点的差异,但哈希值是齐全不雷同的。同时依据哈希值,是很难反向推导出原始数据。 MD5("我明天讲哈希算法!") = 425f0d5a917188d2c3c3dc85b5e4f2cbMD5("我明天讲哈希算法 ") = a1fb91ac128e6aa37fe42c663971ac3d哈希算法要解决的文本可能是各种各样的。 比方,对于十分长的文本,如果哈希算法的计算工夫很长,那就只能停留在实践钻研的层面,很难利用到理论软件开发中。比方,把明天的这篇蕴含4000多个汉字的文章,用MD5计算哈希值,用不了1ms的工夫。02.哈希算法的利用Hash有哪些风行的算法 目前风行的 Hash 算法包含 MD5、SHA-1 和 SHA-2。哈希算法次要有哪些 MD5算法:MD5,MD5+盐SHA算法:蕴含5个算法,别离是SHA-1、SHA-224、SHA-256、SHA-384和SHA-512,后四者并称为SHA-2。哈希算法的利用十分十分多,选了最觉的七个 别离是平安加密、惟一标识、数据校验、散列函数、Git版本控制、云存储、数据分片。03.平安加密的场景说到哈希算法的利用,最先想到的应该是平安加密。 最罕用于加密的哈希算法是MD5(MD5 Message-Digest Algorithm,MD5音讯摘要算法)和SHA(Secure Hash Algorithm,平安散列算法)。除了这两个之外,当然还有很多其余的加密办法,比方DES(Advance Encryption Standard,高级加密规范)。对用于加密的哈希算法来说,有两点很重要:第一是很难依据哈希值反向推导出原始数据,第二是散列抵触的概率要很小。 第一点很好了解,加密的目标就是不会悔恨原始数据泄露,所以很难通过哈希值反向推导出原始以数据,这是一个根本要求。重点说说第二点,但不论什么哈希算法,咱们只能尽量减少碰撞抵触的概率,实践上是没方法做到齐全不抵触的,这是为什么呢?基于组合数学中一个叛党根底的实践,鸽巢原理(也叫抽屉原理)。 这个原理自身很简略,它是说,如果有10个鸽巢,有11只鸽子,那必定有1个鸽巢中的鸽子数量大于1,换句话说就是,必定有一个巢里的鸽子数量大于1。哈希算法产生的哈希值的长度是固定且无限的。比方后面说的MD5的鸽子,哈希值是固定的128位二进制串,能示意的数据是无限的,最多示意2^128个数据,而咱们要哈希的数据能够是无穷的,那必然会存在哈希值雷同的状况。如果咱们拿到一个MD5哈希值,心愿通过毫无法则的穷举的办法,找到这个MD5值雷同的另一个数据,那消耗的工夫应该是个天文数字了。即使哈希算法实践上存在抵触,但还是很难破解的。除此之外,没有相对平安的加密。 越简单、越难破解的加密算法,须要的计算工夫也越长。比方SHA-256比SHA-1要更简单、更平安,相应的计算工夫就会比拟长。04.惟一标识的场景先举个例子。如果要在海量的图库中,搜寻一张图是否存在,咱们不能单纯地用图片的元信息(比方图片名称)来比照,因为有可能存在名称雷同但图片内容不同,或者名称不同图片内容雷同的状况。那咱们该如何搜寻呢? 任何文件在计算机中都能够示意成二进制码串,所以,比拟笨的方法就是,拿要查找的图片的二进制码串与图库中所有图片的二进制码串逐个比对。如果雷同,则阐明图片在图库中存在。然而,每个图片小则几十KB、大则几MB,转化成二进制是一个十分长的串,比对起来十分耗时。有没有比拟快的办法呢?能够给每一个图片取一个惟一标识,或者说信息摘要。 比方,咱们能够从图片二进制码串开关取100个字节,从两头取100个字节,从最初取100个字节,而后将这300个字节放一块。通过这个惟一标识来断定图片是否在图库中,这样就能够缩小很多工作量。如果还想持续提高效率,咱们能够把每个图片的惟一标识,和相应的图片文件在图库中的门路信息,都存储在散列表中。 当要查看某个图片是不是在图库的时候,咱们先通过哈希算法对这个图片取惟一标识,而后在散列表中查找是否存在这个标识。如果不存在,那就阐明这个图片不在图库中,如果存在,咱们再通过散列表存储的文件门路,获取到这个曾经存在的图片,跟当初要插入的图片做全量的比对,看是否齐全一样,如果一样,就阐明曾经存在;如果一一样,阐明两张图片只管惟一标识雷同,然而并不是雷同的图片。05.数据校验的场景电驴这样的BT下载软件听过吧!BT下载的原理是基石地P2P协定的。 咱们从多个机器上并行下载一个2GB的电影,这个电影文件可能会被宰割成很多文件块(比方能够分成100块,每块大概200MB)。等所有的文件块都下载实现之后,再组装成一个残缺的电影文件就行了。网络传输是不平安的,下载的文件块有可能是被宿主机歹意批改过的,又或者下载过程中呈现了谬误,所以下载的文件块可能不是残缺的。如果咱们没有能力检测这种歹意批改或者文件下载出错,就会导致最终合并后的电影无奈观看,甚至导致电脑中毒。当初的问题是,如何来校验文件块的平安、正确、残缺呢?具体的BT协定很简单,校验办法也有很多,我来说其中的一种思路。 咱们通过哈希算法,对100个文件块别离取哈希值,并且保留种子文件中。在后面讲过,哈希算法有一个特点,对数据很敏感。只有文件块内容有一丁点儿的扭转,最初计算出的哈希值就会齐全不同。所以,当文件块下载实现之后,咱们能够通过雷同的哈希算法,对下载好的文件逐个求哈希值,而后跟种子文件中保留的哈希值比对。如果不同,阐明这个文件块不残缺或者被篡改了,须要再从新从其余宿主机上下载这个文件块。06.散列函数的场景散列函数是设计一个散列表的要害。 它间接决定了散列抵触的概率和散列表的性能。不过,绝对哈希算法的其余利用,散列函数对于散列算法抵触的要求要低很多。即使是呈现个别散列抵触,只有不是过于重大,咱们都能够通过凋谢寻址法或者链表法解决。不仅如此,散列函数对于散列算法计算失去的值,是否能反向解密也并不关怀。散列函数中用到的散列算法,更加关注散列后的值是否能均匀散布,也就是,一组数据是否能平均的散列到各个槽中。除此之外,散列函数执行的快慢,也会影响散列表的性能,能以,散列函数用的散列算法个别都比较简单,比拟谋求效率。最常见的散列函数利用场景 比方工业存储key-value汇合HashMap数据结构,存储key就用到了散列函数!HashMap为何对key应用哈希算法 hash值(key)存在的目标是减速键值对的查找,key的作用是为了将元素适当地放在各个桶里,对于抗碰撞的要求没有那么高。07.Git版本的管制以Git为代表的泛滥版本控制工具都在应用SHA1等散列函数查看文件更新 包含GitHub在内的泛滥版本控制工具以及各种云同步服务都是用SHA1来区别文件,很多平安证书或是签名也应用SHA1来保障唯一性。长期以来,人们都认为SHA1是非常平安的,至多大家还没有找到一次碰撞案例。08.云存储文件场景当初大部分的网络部署和版本控制工具都在应用散列算法来保障文件可靠性。 在进行文件系统同步、备份等工具时,应用散列算法来标记文件惟一性能帮忙咱们缩小零碎开销,这一点在很多云存储服务器中都有利用。当原有文件产生扭转时,其标记值也会产生扭转,从而通知文件使用者以后的文件曾经不是你所需要的文件。散列函数很难可逆 这种不可逆性体现在,你不仅不可能依据一段通过散列算法失去的指纹来取得原有的文件,也不可能简略地发明一个文件并让它的指纹与一段指标指纹相一致。09.哈希算法的总结第一个利用是惟一标识,哈希算法能够对大数据做信息摘要,通过一个较短的二进制编码来示意很大的数据。第二个利用是校验数据的完整性和正确性。第三个利用是平安加密,任何哈希算法都会呈现散列抵触,然而这个抵触的概率十分小。越是简单的哈希算法越难破解,但同样计算工夫也就越长。所以,抉择哈希算法的时候,要衡量安全性和计算工夫来决定用哪种哈希算法。第四个利用是散列函数,这个咱们后面讲散列表的时候具体说过,它对哈希算法的要求十分特地,更加看重的是散列的均匀性和哈希算法的执行效率。10.哈希算法的特点正向疾速: 给定明文和 hash 算法,在无限工夫和无限资源内能计算出 hash 值。逆向艰难: 给定(若干) hash 值,在无限工夫内很难(根本不可能)逆推出明文。输出敏感: 原始输出信息批改一点信息,产生的 hash 值看起来应该都有很大不同。抵触防止: 很难找到两段内容不同的明文,使得它们的 hash 值统一(发生冲突)。即对于任意两个不同的数据块,其hash值雷同的可能性极小;对于一个给定的数据块,找到和它hash值雷同的数据块极为艰难。11.哈希算法的实际提供几个简略的概念供大家参考 作为散列算法,首要的性能就是要应用一种算法把原有的体积很大的文件信息用若干个字符来记录,还要保障每一个字节都会对最终后果产生影响。那么大家兴许曾经想到了,求模这种算法就能满足咱们的须要。事实上,求模算法作为一种不可逆的计算方法,曾经成为了整个古代密码学的根基。只有是波及到计算机平安和加密的畛域,都会有模计算的身影。 散列算法也并不例外,一种最原始的散列算法就是单纯地抉择一个数进行模运算,比方以下程序。 # 结构散列函数def hash(a):return a % 8# 测试散列函数性能print(hash(233))print(hash(234))print(hash(235))123 上述的程序实现了一个散列算法所该当实现的高级指标:用较少的文本量代表很长的内容(求模之后的数字必定小于8)。但兴许你曾经留神到了,单纯应用求模算法计算之后的后果带有显著的规律性,这种法则将导致算法将能难保障不可逆性。所以咱们将应用另外一种伎俩,那就是异或。在散列函数中退出一个异或过程 ...

February 2, 2023 · 2 min · jiezi

关于android:Android耗电分析之Battery-Historian工具使用

Battery-Historian是谷歌推出的一款专门剖析Bugreport的工具,是谷歌在2015年I/O大会上推出的一款检测运行在android5.0(Lollipop)及当前版本的设施上电池的相干信息和事件的工具,是一款对于剖析手机状态,历史运行状况很好的可视化剖析工具。 当设施在应用电池的时候,它能够使开发者们看到零碎级和利用级事件图表,在图表时间轴上能够缩放和平移,可能直观的看到自上一次充斥电到当初设施电池的统计汇总信息,它能够选中一个应用程序来查看该利用影响电池电量的一些参数,并且能够比照两个bugreport文件信息剖析,并对其电池要害区别点做高亮显示。 不过,须要留神的是,battery historian在应用时候不能在充电,同时确保设施运行在Android 5.0及以上版本。而对于Android8.0及其以上版本,咱们更举荐应用Android Studio自带的Energy Profiler工具。 一、Battery Historian环境battery historian剖析须要装置Docker,其装置和运行办法官网有具体的阐明:Battery Historian装置。可能在本地装置Battery Historian环境还比拟繁琐,此次举荐一个他人搭建好的地址:https://bathist.ef.lc/。 二、生成耗电报告耗电统计是零碎组件,随同零碎运行的整个过程,也就是说只有零碎在运行它就会始终统计耗电数据。这个统计是基于软件层面实现的,不同的硬件模块配置了不同的参数,而后应用算法进行估算,power_profile文件的参数值OEM厂商必须测量并提供前理论值,所以不同的厂商是不一样的。 另外,获取统计报告的时候须要将重置统计,并断开usb连贯,并且不能处于充电状态,否则会大大影响统计的后果。上面是应用步骤: 连贯手机,关上开发者模式,而后连贯adb。重置batterystats 数据, 手机始终在后盾收集batterystats和其余调试信息,重置的命令:adb shell dumpsys batterystats –reset继续应用咱们须要测试的利用,而后导出原始bugreport数据,导出的命令://Android 7.0及以上版本adb bugreport bugreport.zip//Android 5.0及以上版本adb bugreport > bugreport.txt期待报告生成,会生成一个bugreport.zip或bugreport.txt文件,如下图。 三、Battery Historian 指标剖析关上https://bathist.ef.lc/网站,抉择bugreport.zip文件并上传。期待剖析后果,剖析实现之后,零碎会生成如下的图表。图表按类别进行组织,随着工夫的推移显示每个类别的栏,如图表的X轴上所示。不同色彩代表指标的不同状态:比方Screen 红色代表亮屏,红色代表关屏,具体鼠标放在最左侧的️上就会主动提醒。 默认状况下,统计信息是在运行根底上保护的,Android也不记录特定于应用程序的用户空间wakelock转换的工夫戳。如果您心愿Historian在工夫线上显示对于每个独自唤醒锁的详细信息,则应在开始试验之前应用以下命令启用残缺唤醒锁报告。 adb shell dumpsys batterystats --enable full-wake-history而后,咱们来看一下具体的指标,剖析前咱们须要抉择某个具体的利用:页面的右下角有几个选项卡,能够用来查看一些具体的性能数据: System Stats:蕴含零碎范畴的统计信息,如单元信号级别和屏幕亮度。这些信息提供了设施产生状况的整体状况。这对确保没有内部事件影响特地有用。App Stats :蕴含无关特定应用程序的信息。应用左侧的应用程序抉择窗格中排序应用程序下拉列表对应用程序列表进行排序。能够抉择一个特定的应用程序来查看应用程序下拉列表的统计信息。同时,在抉择应用程序后,咱们还能够抉择某个具体的场景进行剖析,如下图。 四、案例剖析应用battery historian进行电量剖析时,通常有如下一些套路: 通过system stats 中screenon/off rate 均匀亮灭屏耗电熟读能够初步确认亮屏或者灭屏耗电是否有异样。通过选取电量值察看每格电量的耗费速度,确认耗电异样时间段和以后前台利用,网络状态,后盾job等信息。综合以后亮度,网络状态,后盾job ,前台利用估算是否合乎预期,确认是否以后配置环境问题,还是利用耗电异样。 上面看几个具体的案例场景: 1,充电慢问题:查看充电电流值,确认充电电流是否合乎预期。查看充电过程是否有异样job在长时间执行,如果有异样job耗电也会升高充电电流。查看对应电池温度是否有低温景象,电池温度过高会限度充电电流。 2,发热问题:通过batterystats查看以后发热状况,找到温度最高区间,综合以后网络,亮度,利用确认耗电状况是否合乎预期。如耗电电流不大,然而温度确继续减少,大概率环境无奈散热导致,比方太阳光直射,物品笼罩无奈散热。 3,亮屏耗电问题:当呈现亮屏耗电时,先查看网络状态,亮度状态,是否高耗电利用。不同网络耗电排行5G>4G>wifi,高亮下耗电会急剧减少,游戏相机场景会耗电大。比方,上面的场景是用户反馈白天耗电快场景(4G下,高亮,加上后盾GPS长时间定位)。 4,息频耗电问题:息屏场景,局部app会通过音频持锁来给本人保活。通过查看audio和wakelock状态能够确认此类问题。app频繁网络包唤醒零碎(利用唤醒频次低于1min),同样也会引起耗电快。比方,上面的场景用户反馈息屏耗电快场景:从batteryhistorian能够看到xfPlay,始终持有音频锁给本人保活,导致系统无奈休眠从而息屏耗电。 5,息屏异样耗电问题:所有信息都合乎预期,然而还是耗电快,此种状况可能是有异样器件漏电问题。比方,上面的场景息屏耗电场景,唤醒周期超过2min,休眠比良好,然而耗电仍旧很大。有可能是器件漏电,须要业余功耗工程师进一步剖析。 电量追赶问题:当发现耗电电流超过理论值,并且无异样发热,大概率是呈现了电量追赶问题。当计算出来的实在电量和理论电量有差别时,理论电量就会疾速降落追赶至实在电量,体现就是30s或者60s一格电的速度去追赶。比方,息屏耗电场景均匀耗电电流5466ma,实践手机不会呈现这么大电流(。此时温度失常,大概率是呈现了虚电,电量追赶问题,须要从kernel 日志进一步剖析确认。Battery Historian图形化工具,能够十分直观查看历史耗电信息,追溯到耗电场景。对于个别用户,Battery Historian剖析简略耗电问题曾经足够。不过,对于更深的耗电问题,则须要更多的辅助日志或者dump 由更业余工程师进一步剖析。

February 2, 2023 · 1 min · jiezi

关于android:开发互动直播应用很简单声网-Android-Demo保姆级跑通教程

本文作者是来自声网开发者社区的用户“Xiaohua”。前言自己在参加《声网开发者漫游指南》期间,通过学习理解和学会跑通声网的实时互动Demo,但因为课程提供的demo是挪动端和pc端的,很少接触过,所以只能花点工夫学习一下能力运行demo我的项目。 鉴于大学学习过java语言,所以抉择了安卓平台的实时互动Demo去尝试运行。Demo的仓库地址: https://github.com/AgoraIO/AP... 下载源码间接下载压缩包即可,而后把它解压到指定目录。 而后要关注的是 Android 目录里的内容,通常上传的代码仓库里都有具体的 README.md 文档提供浏览,所以咱们须要看一下有没有搭建开发环境的步骤。 在 API-Examples/Android/APIExample/README.md 中,有阐明了环境的筹备: 环境筹备因为 Android Studio 是收费应用了,所以不必激活码这些了,间接到官网下载安装包装置即可。 装置过程就比较简单了,看得懂英文和 next 始终点就差不多了。 装置结束后,首次关上会查看咱们想在电脑上装置的 Android SDK 组件,这里比拟久,须要花一些工夫。 关上 Android Studio 后,点击 Open 抉择 Android 我的项目,文件图标会有非凡显示的就是我的项目文件了: 关上我的项目后,会进行 build,下载 Gradle 下载实现而后显示BUILD SUCCESSFUL就示意构建实现,我的项目目录构造会变成下图所示: 到此为止我的项目就胜利关上并且build胜利了。接下来就要在Android Studio外面应用模拟器去运行咱们的Demo我的项目了。 在模拟器上运行Demo在工具栏中,从指标设施下拉菜单中抉择要用来运行利用的 AVD。一开始是没有模拟器的,须要咱们装置一个。 装置完后,选中一个模拟器,而后点绿色三角形run 胜利运行demo! 然而这时候是运行不了外面的例子的,还须要配置一下数据。在README.md外面也提到让咱们到声网的控制台创立一个我的项目。 获取appId并运行前提是咱们声网开发者账号,并进行实名认证了才能够创立我的项目的。 创立咱们的实时互动我的项目,我抉择的是视频通话类型的。 而后点进我的项目里能够复制appid。 创立一个长期的token。 运行我的项目后,输出appid、token以及channelId即可进行视频通话了,因为我的电脑没有摄像头,所以连上真机调试。以下是运行的一个不必填token的,然而须要配置一下xml。最终成果如下。(这里为了不裸露隐衷信息,前期马赛克掉了一些画面。) 如在开发过程中遇到疑难,可在声网开发者社区与官网工程师交换。

January 31, 2023 · 1 min · jiezi

关于android:音频编辑服务UI-SDK接入指导及常见问题

华为 HMS Core 音频编辑服务(Audio Editor Kit)是华为帮忙寰球开发者疾速构建各类利用音频能力的服务,汇聚了华为在音乐、语音等相干音频畛域的先进技术。音频编辑服务为开发者们提供音频根底编辑、AI配音、音源拆散、空间渲染、变声、多种音效等丰盛的音频解决能力,以及性能优异、简略易用、开放性强的接口,开发者们可根据利用场景,在App中高效轻松实现音频性能的集成。 音频编辑UI SDK提供产品级UI界面,集成接入简略、疾速。 开发筹备1、配置AppGallery Connect 2、配置HMS Core SDK的Maven仓地址 3、集成HMS Core SDK 4、在“AndroidManifest.xml”文件中增加相干权限。 阐明:如果利用集成的Android SDK版本为29及以上时,还须要在AndroidManifest.xml的application节点下新增以下属性,以获取拜访内部存储文件的权限。 <application android:requestLegacyExternalStorage="true" …… >反对的设施REST Android: 华为手机 EMUI5.0 及以上 非华为手机 Android7.0 及以上 SDK集成开发1、初始化SDK,设置利用的鉴权信息,如果不设置将影响局部性能的应用。 // 获取agconnect-services.json文件中的api_key。// 正式利用中倡议将api_key存储在云侧,运行时在进行获取。String api_key = AGConnectInstance.getInstance().getOptions().getString("client/api_key");// 设置api_keyHAEApplication.getInstance().setApiKey(api_key);2、创立AudioFilePickerActivity,此Activity为自定义Activity,用于音频文件抉择。 /** * 自定义Activity界面,用于音频文件的抉择 */public class AudioFilePickerActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); performFileSearch(); } private void performFileSearch() { // 抉择多个音频文件 registerForActivityResult(new ActivityResultContracts.GetMultipleContents(), new ActivityResultCallback<List<Uri>>() { @Override public void onActivityResult(List<Uri> result) { handleSelectedAudios(result); finish(); } }).launch("audio/*"); } /** * 解决选定的音频,将Uri转成须要的门路 * * @param uriList 选中的音频文件 */ private void handleSelectedAudios(List<Uri> uriList) { // 判断是否存在音频文件 if (uriList == null || uriList.size() == 0) { return; } ArrayList<String> audioList = new ArrayList<>(); for (Uri uri : uriList) { // 获取实在门路 String filePath = FileUtils.getRealPath(this, uri); audioList.add(filePath); } // 将音频文件门路返回给音频编辑页面 Intent intent = new Intent(); // 应用SDK提供的HAEConstant.AUDIO_PATH_LIST intent.putExtra(HAEConstant.AUDIO_PATH_LIST, audioList); // 应用SDK提供的HAEConstant.RESULT_CODE为后果CODE this.setResult(HAEConstant.RESULT_CODE, intent); finish(); }}获取实在门路时用到的FileUtils工具类,能够在示例代码中查看,工具类门路为: ...

January 31, 2023 · 2 min · jiezi

关于android:Android-调试实战与原理详解

图片来自:https://101.dev/ 本文作者: 雪谷前言调试性能做为开发的必备神技,熟练掌握后能极大的进步开发效率,再也不用为频繁运行代码而苦恼了。文章同时还会具体介绍调试的原理以及一些调试过程中的常见问题,想晓得为什么办法断点那么慢? 接下来将从以下四个方面来解说调试是如何运作的: 调试操作调试实战调试原理常见问题调试简介这里咱们介绍一下调试的常见操作,灵便把握这些操作,能够帮忙咱们疾速定位到对应代码或者获取想要的信息。 运行调试开启 Debug 调试模式有两种形式: Debug Run:间接以 Debug 模式运行 APP,该模式的长处是能够调试程序启动相干的代码,例如 Application.onCreate()。 Attach To Process:在程序运行中抉择过程来调试,该模式的长处是随时可开启、敞开 Debug 模式,应用灵便不便。 留神:Debug Run 会导致程序整体变慢,倡议应用期待调试,应用该形式能够在启动利用后处于期待状态,在开启调试后,利用才会走初始化流程,有两种形式开启期待断点: 办法1:「开发者选项 - 抉择调试利用」的形式来调试利用启动阶段代码。具体形式为「抉择调试利用」-> 「运行利用」-> 「Attach To Process」,而后期待断点执行即可。 办法2:应用adb命令adb shell am set-debug-app -w --persistent 包名开启,「-w」即示意利用启动时期待调试程序;敞开应用adb shell am clear-debug-app。 调试操作上面介绍一下 Debug 过程中的常见操作: Show Execution Point:跳到以后执行的断点处。Step Over:单步执行,执行到以后行的下一行。Step Into:进入正在执行的办法。Focus Step Into:同3,然而能够进入源码,在3无奈进入的状况下,能够尝试该操作。Step Out:跳出正在执行的办法。Drop Frame:返回到以后办法的调用处。Run to Cursor:运行到光标处(光标必须在以后断点地位后)。Evaluate expression:计算选中的变量的值。断点类型 断点分为以下四种类型: 行断点: 当执行到此行是进行执行,期待调试。 属性断点:打在类的成员变量上,当变量初始化或变量的值扭转时触发断点。 异样断点:当抛出指定异样时触发断点。 办法断点:当须要晓得一个办法的调用方时。 这里着重讲一下办法断点的应用场景: 如下所示,有个接口 IMethodTest,同时有两个类 MethodTestImpl1 和 MethodTestImpl2 实现了该接口,在 IMethodTest 的 printMethod() 上打上办法断点。 ...

January 31, 2023 · 3 min · jiezi

关于android:由浅入深聊聊-LeakCanary-的那些事

引言对于内存透露,Android 开发的小伙伴应该都再相熟不过了,比方最常见的动态类间接持有了某个 Activity 对象,又比方某个组件库的订阅在页面销毁时没有及时清理等等,这些状况下少数时都会造成内存透露,从而对咱们App的 晦涩度 造成影响,更有甚者造成了 OOM 的状况。 在现代化开发以及多人合作的背景下,如何能做到开发中疾速的监测内存透露,从而尽可能杜绝上述问题,此时就显得更加尤为重要。 LeakCanary 就是一个能够帮忙开发者疾速排查上述问题的工具,简直所有的Android开发者都曾应用过这个工具,其背地的设计也是各厂自研相应组件的借鉴思维。 而了解 LeakCanary 背地的设计思维与原理,也更是每个应用层开发者所必不可少的技能点。 故此,本篇将以最新的视角,与你一起使劲一瞥 LeakCanary。 LeakCanary 版本:2.10 本篇定位 中等,将从背景到应用形式,再到源码解析,尽可能全面、易懂。根底概念在开始之前,咱们还是要解释一些常见的根底问题,以便更好的了解本篇。 什么是内存透露?当咱们App无奈开释不须要的对象援用时,即为内存透露。也能够了解为,生命周期长的持有了生命周期短的对象所导致。 常见内存透露场景?非动态外部类与匿名外部类(导致的持有外部类援用时,比方Act中的非动态Handler);异步线程持有内部 context(非AppContext)援用所导致的内存透露;service 遗记理解绑或者播送没有解除订阅等;stream 流遗记敞开;…LeakCanary 应用形式对于 LeakCanary 的应用形式,老手小伙伴能够从 官网文档 失去更多,这里仅仅只是作为一个简略概要。 debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10'LeakCanary 应用很简略,只须要在gradle中增加依赖即可,就是这么 Easy :) 而后当咱们app运行后,桌面会装置一个 名为 Leask 的软件,icon是一个小鸟的图标。 如果 app 在应用中呈现内存透露并且达到肯定数量时,其会自动弹出一个告诉,提醒咱们进行内存透露剖析。当点击告诉后,LeakCanary 会进行透露堆栈剖析,并将其显示到 Leask 的透露列表中。开发者能够通过具体的 item 从而理解相应的透露信息,当然也通过查看 log 日志进行剖析。具体如下图所示(官网截图): 源码剖析这一章节,咱们将从 LeakCanary 的源码登程,从而摸索其背地的设计思维。 如何初始化问起这个问题,稍有教训的开发者必定都会猜到,既然不须要手动初始化,那必定是 ContentProvider 了。 如下所示: internal class MainProcessAppWatcherInstaller : ContentProvider() { override fun onCreate(): Boolean { val application = context!!.applicationContext as Application AppWatcher.manualInstall(application) return true } }其外部减少一个 ContentPrvider ,并在 onCreate() 进行初始化。 ...

January 30, 2023 · 3 min · jiezi

关于android:鹅鸭杀爆火一文带你了解如何实现顶流社交游戏

2023 年开年,一款名为《鹅鸭杀》(Goose Goose Duck)的社交游戏异军突起,不仅吸引了很多萌新玩家,还让各大平台的出名游戏主播们沉迷其中,与粉丝们一起夜夜开黑。 《鹅鸭杀》的玩法与太空狼人杀十分类似。在游戏中,玩家分为三个营垒:坏蛋(鹅)、好人(鸭)、中立(其余鸟类)。鹅与鸭的对抗角色很好了解,而中立角色千奇百怪,有几十种角色,比方取得被害鹅的尸体即可获胜的“秃鹫”、生存到最初即可获胜的“猎鹰”等,其中还有个“鹈鹕”角色,能够把其它玩家吞到肚子里,这些玩家依然能够发言,但只有他们本人和鹈鹕能听到。所以还会呈现一堆人在鹈鹕肚子里“开演唱会”的搞笑场景。 目前,这款游戏已吸引大量玩家。依据 SteamDB 的数据(如上图),每天的玩家峰值至多有 55 万人。而且,这款游戏曾经冲进 Steam 平台热销榜单的前五名。尽管这样的热度不易复制,但它的玩法场景却能够基于声网 SDK 轻松实现,甚至做出一些差异化的翻新。 浅析鹅鸭杀的实现原理其实《鹅鸭杀》的玩法与太空狼人杀类似,依据声网的教训来讲,实现起来并不艰难。咱们先来剖析一下游戏中最常见的互动场景: ①工作摸索环节:玩家共有 16 人,在地图中走近时能语音交换,走远后语音音量削弱直至隐没。玩家在地图中,处于不同房间的人,听不到对方的声音。②投票环节:散会投票时,所有玩家不管在地图中什么地位,都能够听到对方的声音。③被鹈鹕吞掉:游戏进行中,如果有玩家被鹈鹕吞掉,则会被拉入 RTC 概念中的“子频道”。在“子频道”中的用户彼此能够听到对方的声音,子频道之外的则无奈听到。在鹈鹕被“剖腹产”之后,玩家退出子频道,复原与其余玩家的语音连麦。实现办法,咱们稍后细讲。 图源自 Steam 以上这些语音互动的场景,都能够通过声网 RTC SDK 来实现。所有玩家在退出游戏之后,会进入同一个大频道,相互能够听到对方的声音。在游戏地图中,每个玩家都有一个地位信息,当玩家们凑近的时候,能够依据地位信息的变动来调整语音的音量,从而实现听觉上的“间隔”感与沉迷感。如果有玩家被鹈鹕吞掉,这些玩家与鹈鹕会进入一个子频道,子频道中的玩家能够相互听到彼此的声音。当鹈鹕被刀了,这些玩家相当于退出了子频道,就能失常与大频道中的其余玩家语音互动。 另外,在游戏过程中,还会有刀人、投票、挪动角色等游戏指令操作。这些都能够通过信令音讯零碎实现。 如何疾速实现这样来看,实现一个《鹅鸭杀》类的产品,并不简单。如果咱们应用声网 SDK 来实现,技术架构如下图所示: **首先所有的游戏指令操作,开发者能够基于本人的信令零碎来实现,也能够通过集成声网 RTM(Real-Time Messaging) SDK 来实现**。依据声网的教训,狼人杀类游戏中的信令音讯对延时的要求并不高。通常状况下,声网 RTM SDK 的延时小于 100ms,齐全能够满足《鹅鸭杀》的场景需要。  而**游戏中的语音互动性能,则能够基于声网 RTC SDK 疾速实现**。咱们以语音互动为例,如果基于声网 SDK 来实现,API 的调用逻辑如下: a.第一步退出游戏房间时,初始化 IRtcEngine; b.因为咱们的游戏是须要连麦互动的,所以第二步是设置 ChannelMediaOption 的参数为 LIVE_BROADCASTING,进入连麦模式; c.第三步调用 joinChannel,让所有玩家退出同一个频道,在这个大频道中,玩家能够进行连麦; d.游戏完结时,调用 LeaveChannel 退出频道,语音的互动也就此结束。 除此之外,《鹅鸭杀》游戏中还有一些非凡的场景,对语音互动提出了额定要求: 1、带物理墙的范畴语音  用户之间如果有墙,声音不能间接穿墙,然而能够从门绕过(总途程小于范畴)。对此,你能够通过调用 setZones 设置隔声区域和声音衰减系数。当音源(能够为用户或媒体播放器)跟听声者分属于音障区域外部和内部时,会体验到相似实在环境中声音在遇到修建隔断时的衰减成果。  2、语音音量依据玩家在游戏中的间隔变动 这个性能实现也比较简单,因为声网 SDK 反对空间音频性能。通过设置 SpatialAudioParams 中的 enable_doppler 参数开启多普勒音效,在声源和接管方产生绝对位移的状况下,接管方会体验到显著的音调变动。 3、回声与降噪 ...

January 30, 2023 · 1 min · jiezi

关于android:安卓逆向之破解某成人APP播放次数限制

前言某成人水果APP非VIP用户存在播放次数限度,每天只能播放3次。超过3次须要购买VIP。 因为过于贫困,于是抽空,对其安卓APP进行了逆向剖析,最终胜利破解了其播放次数限度。 破解思路思路一通过应用发现,当我点击列表,跳转至视频详情页时,播放次数就会减一。如果APP开发人员,更改播放次数和获取视频详情时应用了两个独自的接口,咱们就能够通过屏蔽更改播放次数的接口,让可播放次数永远不缩小,从而实现有限播放 思路二APP存在匿名注册,装置并关上APP后,无需手机号和邮箱,会主动生成一个匿名账号。这种匿名注册个别都是会依据手机硬件相干的信息生成uid。这样的话,能够在每次播放次数用完后,hook手机硬件相干的API, 返回新的硬件信息,注册新的匿名账号,从而实现有限播放 抓包有了大抵思路,老规矩,先抓包看看APP的接口信息。关上BurpSuite, 配置代理。发现申请和响应都存在加密。 所以须要先解密。 查找解密函数因为App最终还是须要应用明文数据的,所以APP中必定有解密函数。 关上Jadx-gui, 将apk关上,发现没有加壳。搜寻申请参数关键字_ver, timestamp,sign等,定位到加密逻辑 EncrytUitl.encrypt这个办法进行了加密,EncryUtil.decrypt 这个办法进行解密。 解密因为加解密都是通过so库实现,逆向出残缺解密逻辑比拟艰难并且也没有必要。所以间接通过frida + brida + burpsuite,间接调用解密函数进行解密 编写frida hook代码function calldecrypt(str) { if (!str) { return; } return new Promise((resolve) => { Java.perform(function x() { const encryptUtil = Java.use('com.qq.lib.EncryptUtil') const ret = encryptUtil.decrypt(str, 'PT0dPVxYXglbDARZXwlfXwwMDApYDgReWV4JXl4ICAtfWAxcJD4WCD8SFRYCFQ==') resolve(ret) }); });}function callencrypt(str) { if (!str) { return; } return new Promise(resolve => { const encryptUtil = Java.use('com.qq.lib.EncryptUtil') const ret = encryptUtil.encrypt(str, 'PT0dPVxYXglbDARZXwlfXwwMDApYDgReWV4JXl4ICAtfWAxcJD4WCD8SFRYCFQ==') resolve(ret) });}rpc.exports = { calldecrypt, callencrypt,}设置brida ...

January 29, 2023 · 1 min · jiezi

关于android:Flutter-耗时监控-路由名为空原因分析

前言最近群里遇到获取Route名为空的问题,过后没在意。。。 直到本人在监控页面启动耗时,须要确定以后页面是哪个从而不便标记它加载的耗时时,遇到同样 route.settings.name 为空问题,模仿场景如下: 在 main.dart 页面中点击 + 按钮跳转到 TestPage2 页面。MaterialApp 中设置路由守卫并在路由守卫中打印 route 名。main.dart launch_observer.dart TestPage2.dart 路由守卫中打印后果如下: 能够看出 利用启动进入 main 打印是正确的,之前没有页面,进入时候打印 route = /进入 TestPage2 时,previewousRoute 的 name = / 正确,然而以后 route 的 settings.name 却为 null ,这就比拟奇怪了。我试着复现文章结尾的例子,代码如下: main.dart 不变,点击 + 跳转到 TestPage2在 TestPage2 中获取路由参数和路由名字<p align=left><img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e2313dfbfdc3463b953fb0900c2f8fe8~tplv-k3u1fbpfcp-watermark.image?" alt="Untitled 5.png" /></p>后果发现:name 的值依然为 null;<p align=center><img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7dae7543a3394aed9e43b95494e03cfd~tplv-k3u1fbpfcp-watermark.image?" alt="Untitled 6.png" width="50%" /></p> 问题剖析MaterialPageRoute 继承关系 最终咱们要失去的 name 其实是 Route 外部的 RouteSettings 对象的 name。 而通过继承关系追溯,最终 Route 中的 RouteSettings② 由 MaterialPageRoute① 传过来。 ...

January 27, 2023 · 1 min · jiezi

关于android:安卓包在真机上安装时的风险提示问题

1)安卓包在真机上安装时的“危险提醒”问题2)iOS下AssetBundle的加载疑难3)特效用粒子系统,模拟器里呈现花屏问题4)IL2CPP编译的Protobuf,反射类运行时报空 这是第321篇UWA技术常识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地把握和学习。 UWA社区主页:answer.uwa4d.comUWA QQ群:465082844 AndroidQ:最近在安卓真机上安装游戏的过程中忽然呈现了危险提醒(以前没有)。有的手机甚至须要输出明码受权能力装置。 如图: 不晓得有没有大佬们最近也遇到了这样的问题,可否提供个批改的思路? A:首先是32位问题,这个是必然要降级的不要挣扎了。至于危险提醒和明码受权,都是国内手机的问题。Rom外面限度了你不上架它的商店就会有这种提醒。OPPO限度了adb间接装置,每次要明码受权。 这些都属于研发层面无从下手的问题,能做的就是倡议玩家别用国产手机。 感激江南@UWA问答社区提供了答复 AssetBundleQ:iOS下AssetBundle加载时候Animator下面失落AnimatorController。 问题:1.0版本里A.prefab是打在AssetsBundle1外面,A.prefab援用的AnimatorController 是打在AssetsBundle2外面,A.prefab上援用的其余资源在AssetsBundle3外面。 2.0版本热更新时,扭转了援用文件的文件夹,A.prefab上援用的AnimatorController生成的Bundle变到了AssetsBundle3外面,A.prefab上援用的其余资源生成的Bundle变到AssetsBundle2外面。 A.prefab所在的AssetsBundle1没有变动,所以热更新上来的是AssetsBundle2和AssetsBundle3。 热更新之后加载AssetsBundle2和AssetsBundle3,再加载AssetsBundle1,运行后发现A.prefab上的Animator组件还在,然而下面的runtimeAnimatorController失落了,变成了Missing。 有人遇到这个问题吗? A1:有一些排查思路,首先在Android平台看下是否也有问题,排除下是否是与平台相干。另外在出问题的机器上预制体模式,如果失常则应用AssetBundle模式来加载看下是否失常,如果是Bundle问题,那能够齐全删除波及到的Bundle从新打一遍再试一下。感激Knight-132872@UWA问答社区提供了答复 A2:Unity上遇到这种问题,最好把A、B、C 3个AssetsBundle包先删除,再打包,让Unity全新生成,应该就好了。感激1 9 7 3-311135@UWA问答社区提供了答复 SimulatorQ:游戏特效用了粒子系统,其余平台都失常,就在模拟器下呈现了花屏问题,时不时地花屏闪动。 特效用了粒子系统的Mesh和Billboard两种模式,而后粒子上挂材质球,是用本人写的Shader,然而切换成Unity自带的URP粒子系统Shader,也一样花屏。不必粒子系统就不会花屏。 用RenderDoc抓帧,只剖析出局部花屏,是用Mesh模式的粒子网格,顶点产生拉扯偏移产生的。然而其余花屏,查不出是哪个对象产生的问题,谁晓得是怎么回事吗? A1:能够尝试换一下Shader的采样精度。感激NG週@UWA问答社区提供了答复 A2:能够尝试一下把粒子特效对应Shader变量类型从fixed改为half或者float。感激beikeshell@UWA问答社区提供了答复 针对以上问题,有教训的敌人欢送转至社区交换分享 BuildQ:IL2CPP编译的Protobuf,反射类运行时报空。问题产生时,会闪崩,闪崩日志信息:Error_Not_Null:"c# exception:System.TypeInitializationException: The type initializer for ‘abcConfigReflection’ threw an exception. —> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.ExecutionEngineException: Attempting to call method 'Google.Protobuf.Reflection.ReflectionUtil+ReflectionHelper`2[[System.IntPtr&, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]::.ctor’ for which no ahead of time (AOT) code was generated.\n... ...

January 18, 2023 · 1 min · jiezi

关于android:Flutter帧率监控-由浅入深详解获取帧率的那些事

前言做线上帧率监控上报时,少不了须要弄明确如何通过代码获取实时帧率的需要,这篇文章通过图解配合Flutter性能调试工具的形式一步步通俗易懂地让你明确获取帧率的基础知识,当前再也不愁看不懂调试工具上指标了。 说说 List<FrameTiming>Flutter 中通过如下形式监听帧率,addTimingsCallback 波及到帧调度常识,感兴趣能够看看这篇Flutter 帧调度过程。 这里重点说说 List<FrameTiming>。 List<FrameTiming>从哪里来addTimingsCallback 定义: List<FrameTiming>可简略了解成:引擎层到框架层的帧数据流。 <p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a0124d1fed7640d094cfc4a473ba7d01~tplv-k3u1fbpfcp-zoom-1.image" alt="" /></p> List<FrameTiming>何时有值List<FrameTiming>则示意一系列实时帧信息。 如点击屏幕按钮,引擎将传递系列帧信息到框架层:“框架层,屏幕发送了变动,筹备回调数据更新了!”。如果用户未操作,addTimesCallback 则不会回调。 因而 ,addTimesCallback(List<FrameTiming>)只有用户操作界面时参数才有值。 List<FrameTiming>中帧存储程序List<FrameTiming>中 0 的地位是第一帧,last 是最新一帧。 最新的帧永远在最初面。 再说说 FrameTiming通过这个单词不难猜测 Frame 示意帧,加上 Timing 能够了解成实时变动的帧。FrameTiming 是一个用来存储实时帧信息的数据结构。 FrameTiming 定义: 这里列了下我认为最重要的几个属性: <p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4a029f915b4041dca4a71892ae532dc4~tplv-k3u1fbpfcp-zoom-1.image" alt="" width="70%" /></p> 前置常识简略阐明了解上述属性前需理解渲染相干常识,不分明的能够看看Vsync 机制 和 卡顿产生起因 。 核心思想图像内容展现到屏幕的过程须要 CPU 和 GPU 独特参加。CPU 负责计算显示内容,比方视图的创立、布局计算、图片解码、文本绘制等。随后 CPU 会将计算好的内容提交到 GPU 去,由 GPU 进行变换、合成、渲染。之后 GPU 会把渲染后果提交到帧缓冲区去,期待下一次 VSync 信号到来时显示到屏幕上。因为垂直同步的机制,如果在一个 VSync 工夫内,CPU 或者 GPU 没有实现内容提交,则那一帧就会被抛弃,期待下一次机会再显示,而这时显示屏会保留之前的内容不变。 FrameTiming 在帧中的示意当在利用中操作时候,就会产生间断的帧,如图: 每两个柱形一起示意一帧:ui 示意 cpu 耗时,raster 示意 gpu 耗时。 ...

January 17, 2023 · 2 min · jiezi

关于android:华为运动健康服务Health-Kit-690版本新增功能揭秘

华为静止衰弱服务(HUAWEI Health Kit)6.9.0版本新鲜出炉啦! 一文理解新增性能,快来一起退出Health Kit生态小家庭! 一、更丰盛:睡眠呼吸记录衰弱数据凋谢呼吸机是用于为患者提供或减少肺通气的罕用医疗器械,目前越来越多的家用呼吸机被用于缓解人们在日常睡眠过程中的打鼾、睡眠呼吸暂停等症状。 HUAWEI Health Kit新增反对在用户受权后,为生态利用凋谢用户在睡眠期间,应用呼吸机时产生的用户睡眠呼吸衰弱数据,助力守护用户的衰弱睡眠。生态利用可读取用户睡眠呼吸记录,如潮气量、低通气指数、阻塞性呼吸暂停指数等多项用户数据指标,剖析用户睡眠呼吸暂停状况,更好地辅助用户睡眠。 二、更多样:路线数据/跑步课程写入反对生态单个路线数据主动导入至华为静止衰弱App,并下发到穿戴设施(反对的设施:HUAWEI WATCH GT 3系列、HUAWEI WATCH GT RUNNER)。用户能够在设施上间接应用下发的路线导航,进行跑步、爬山等流动,无需掏出手机,应用手表即可轻松导航。 反对生态利用的跑步课程数据写入至华为静止衰弱App,并在已有的华为智能穿戴设施连贯并反对课程导入时,间接将课表推送到设施上,用户能够轻松便捷地投入到跑步课程训练中。提醒:跑步课程数据写入处于beta阶段,欢送开发者试用。 理解更多详情>> 拜访华为开发者联盟官网 获取开发领导文档 华为挪动服务开源仓库地址:GitHub、Gitee 关注咱们,第一工夫理解 HMS Core 最新技术资讯~

January 17, 2023 · 1 min · jiezi

关于android:ABAP-Memory-Inspector-里对动态内存对象的内存消耗度量方式

ABAP 动态内存对象是其大小在设计时由数据类型申明设置的对象。 除非更改程序代码自身,否则程序中此类变量占用的内存不会更改。 在 ABAP 术语中,动态变量也称为 flat variable 或 flat Component. 上面是这种类型的变量在 ABAP Memory Inspector 里显示的例子: 值语义(Value semantics)和援用语义(reference semantics)形容了动态内存对象在多个变量援用它时的两种行为形式。 用于特定类型的动态内存对象的语义对该类型的对象应用内存的形式产生重要影响。 实质上,应用值语义的援用变量总是有它本人的、惟一的它所援用的内存对象的正本。值语义变量相似于动态变量; 像动态变量一样,它间接绑定到它所代表的内存对象。只管变量只是一个援用,但从语义上讲,它是内存对象自身。 相比之下,应用援用语义的援用变量被了解为指向内存对象的指针。 内存对象在语义上独立于援用变量。对象能够在许多这样的变量之间共享。 应用值语义解析对 ABAP 外部表、字符串或 boxed Component 的多个援用。 外部表、字符串或 boxed Component 的每个变量都指向它本人的内存对象的独自正本。将表、字符串或 boxed Component 调配给第二个 ABAP 变量会触发对象的复制操作,以便每个变量都有本人的对象正本。通过特定变量对外部表、字符串或 boxed Component 所做的更改,对于已调配给同一对象的其余变量是不可见的。看个具体的例子: DATA t1 TYPE STANDARD TABLE OF xyz.DATA t2 TYPE STANDARD TABLE OF xyz.DATA t_wa type xyz....t2[] = t1[].从语义上讲,T1 和 T2 各自有本人的内表公有正本。 因为 ABAP 的惰性复制(lazy copy)策略,T1 和 T2 以后都指向内存中的单个外部表。 如果表有 1000 行,长度为 20 字节,那么当初拍摄的 memory snapshot 将显示 20 KB 的动静对象内存,即一个表的大小。 ...

January 16, 2023 · 1 min · jiezi

关于android:混合开发之JSBridge安卓或IOS和H5交互

原生调用Web端代码WebView是Native中加载网页的一个控件,该组件提供一个evaluateJavascript()办法运行JS代码。咱们要做的是在Native端执行一个js办法,在Web端进行监听。 Web端定义方法window.doit=function(data){ console.log(data);};原生调用webView.evaluateJavascript("window.doit('来自原生的数据')", null);Web端调用原生代码当Web端要申请Native端的办法时,咱们首先要自定义一个URL Schema,向Native端发动一个申请,最初在Native端的WebView进行监听。 URL schema介绍URL schema 是类URL的申请格局,如:<protocol>://<domain>/<path>?<query> Web端发送URL schema申请比方咱们能够通过批改一个暗藏的iframe地址来实现发送申请: <iframe src="jsbridge://showToast?text=来自Web端端数据"></iframe>舒适提醒:失常来说是能够通过window.location.href达到发动网络申请的成果的,然而有一个很重大的问题,就是如果咱们间断屡次批改window.location.href的值,在Native层只能接管到最初一次申请,后面的申请都会被疏忽掉。所以JS端发动网络申请的时候,须要应用iframe,这样就能够防止这个问题。 原生实现监听安卓在Android中(WebViewClient里),通过shouldoverrideurlloading能够捕捉到url scheme的触发: private WebViewClient webViewClient = new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url){ //读取到url后自行进行剖析解决 //如果返回false,则WebView解决链接url,如果返回true,代表WebView依据程序来执行url return true; }}舒适提醒:另外,Web中也能够不通过iframe.src来触发scheme,通过window.prompt(uri, "");来触发scheme,而后原生中通过重写WebViewClient的onJsPrompt来获取uri。

January 16, 2023 · 1 min · jiezi