那些年的Android开发经验记录

Android Studio 新版Logcat 从惊艳到放弃

AS总算更新了这个logcat了,原来的logcat真是使用起来贼难受,动不动过滤就失效,或者日志不打印,新版的logcat初步使用下来,那是贼舒服,先上一张界面图



  • 一眼看去,可以看到主要改变有三点:

一个是多窗口支持,可以同时打开多个logcat窗口,这对于分析繁多复杂的日志十分有帮助,并且每个窗口又可以复制出多个子窗口,对于分析对比当前窗口不同位置的日志是非常有帮助的;

一个是过滤方式,改成了类似于Github里的搜索过滤语法,可以多个语法组合进行过滤,自定义更强更灵活了;

一个是打印格式,优化了多行日志的打印,日志排版也更清新,也支持了颜色高亮。并且打印信息也可以自定义是否显示

接下来就详细介绍一下这个过滤语法

过滤语法

package:mine 默认语法,官方原版解释:PIDs for the local app project,不太理解这个解释,不过根据使用,应该就是当前logcat窗口所在项目的log

package:my-package-ID 也就是根据包名过滤

tag:my-tag 根据tag进行过滤

level:ERROR 根据日志等级进行过滤

-tag:exclude-this-tag 在前面加了个‘-’,排除指定的TAG

tag~:regex-tag 在后面加了个’~',支持正则过滤

-tag~:exclude-this-regex-tag 这个自然就是支持正则过滤排除指定TAG

-package:exclude-this-package 同上

package~:regex-package 同上

-package~:exclude-this-regex-package 同上

总结

更新的内容挺好的,不过该有的问题依然存在,还是时不时的不显示logcat,需要重新插拔一下手机才行

后续

放弃了,日志更新不及时,删除也不及时,有些日志还没捕获到,比原来的logcat还垃圾,基本问题没解决,上层功能做的再花俏有什么卵用

退回旧版

Settings-> Experimental -> [x] Enable new Logcat tool window 取消选择 -> 重启 Android Studio

Android P以上隐藏API(非SDK接口)反射限制解决方案

相关限制说明参考:针对非 SDK 接口的限制

FreeReflection github

  • Java层双重反射 (Android P)
  • ClassLoader置空 (Android P+)(将被修复)
  • native层通过偏移获取关键结构体然后修改其中的检查Flag (Android P+)

RestrictionBypass github

  • Java层双重反射 (Android P)
  • native层双重反射 (通过AttachCurrentThread隐藏未知调用者) (Android Q+) (将被修复)

AndroidHiddenApiBypass github

  • 借用Unsafe重写反射代码(Android P+)

总结

目前本人仅使用了FreeReflection,不过由于时常报native层闪退异常已弃用(猜测是ClassLoader置空方案造成的,双重反射应该只在Android P生效,native层修改Flag未用到),其他暂未使用,不做评价,不过理论上比较看好AndroidHiddenApiBypass,纯Java,兼容性肯定是最好的,由于Unsafe涉及到native层访问,恐怕不太好封,限制访问部分内存区域?还是直接限制访问反射相关结构体?RestrictionBypass的native层双重反射应该也容易被检测修复

Android 10以上无法隐藏应用图标问题探究及解决方案

Android 10之前的隐藏方式:

con.getPackageManager().setComponentEnabledSetting(new ComponentName(con,activityAliasName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);

Android 10之后,该隐藏图标方式失效,隐藏成功后依然会在桌面上保留其图标,点击后会跳转到应用详情页。具体查看官方API更新说明:getActivityList 。

那这就很难受了,在我看来,目前设计的并不太合理,能不能隐藏应该由用户决定,而不是强制不允许隐藏,不过目前官方也设置了控制开关,可以修改系统设置来去掉该限制,只不过需要adb或能修改系统设置的APP或ROOT权限才能修改。接下来就是具体分析了。

具体分析

  • getActivityList
//frameworks/base/core/java/android/content/pm/LauncherApps.javapublic List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {logErrorForInvalidProfileAccess(user);try {return convertToActivityList(mService.getLauncherActivities(mContext.getPackageName(),packageName, user), user);} catch (RemoteException re) {throw re.rethrowFromSystemServer();}}
  • getLauncherActivities
//frameworks/base/services/core/java/com/android/server/pm/LauncherAppsService.java
@Override
public ParceledListSlice<LauncherActivityInfoInternal> getLauncherActivities(String callingPackage, String packageName, UserHandle user) throws RemoteException {//查询包含ACTION_MAIN和CATEGORY_LAUNCHER的activityParceledListSlice<LauncherActivityInfoInternal> launcherActivities =queryActivitiesForUser(callingPackage,new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER).setPackage(packageName),user);//检测系统设置(系统设置控制开关控制是否走新版限制逻辑)if (Settings.Global.getInt(mContext.getContentResolver(),Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 1) == 0) {return launcherActivities;}//没有找到入口activityif (launcherActivities == null) {// Cannot access profile, so we don't even return any hidden apps.return null;}final int callingUid = injectBinderCallingUid();final long ident = injectClearCallingIdentity();try {//托管配置文件可以隐藏APPif (mUm.getUserInfo(user.getIdentifier()).isManagedProfile()) {// Managed profile should not show hidden appsreturn launcherActivities;}//设备管理员可以隐藏APPif (mDpm.getDeviceOwnerComponentOnAnyUser() != null) {// Device owner devices should not show hidden appsreturn launcherActivities;}final ArrayList<LauncherActivityInfoInternal> result = new ArrayList<>(launcherActivities.getList());if (packageName != null) {// If this hidden app should not be shown, return the original list.// Otherwise, inject hidden activity that forwards user to app details page.//可能是如果大于0,表示有有效的启动入口,则不用注入隐藏的APP详情页入口if (result.size() > 0) {return launcherActivities;}final ApplicationInfo appInfo = mPackageManagerInternal.getApplicationInfo(packageName, /* flags= */ 0, callingUid, user.getIdentifier());//根据APP信息进行判断是否注入隐藏APP详情页入口if (shouldShowSyntheticActivity(user, appInfo)) {LauncherActivityInfoInternal info = getHiddenAppActivityInfo(packageName,callingUid, user);if (info != null) {result.add(info);}}return new ParceledListSlice<>(result);}final HashSet<String> visiblePackages = new HashSet<>();for (LauncherActivityInfoInternal info : result) {visiblePackages.add(info.getActivityInfo().packageName);}final List<ApplicationInfo> installedPackages =mPackageManagerInternal.getInstalledApplications(/* flags= */ 0,user.getIdentifier(), callingUid);for (ApplicationInfo applicationInfo : installedPackages) {if (!visiblePackages.contains(applicationInfo.packageName)) {if (!shouldShowSyntheticActivity(user, applicationInfo)) {continue;}LauncherActivityInfoInternal info = getHiddenAppActivityInfo(applicationInfo.packageName, callingUid, user);if (info != null) {result.add(info);}}}return new ParceledListSlice<>(result);} finally {injectRestoreCallingIdentity(ident);}
}
  • shouldShowSyntheticActivity
//frameworks/base/services/core/java/com/android/server/pm/LauncherAppsService.java
private boolean shouldShowSyntheticActivity(UserHandle user, ApplicationInfo appInfo) {//没有app信息,是系统APP或者更新的系统APP,则不添加隐藏详情页入口if (appInfo == null || appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {return false;}//是管理员APP也不用添加该入口if (isManagedProfileAdmin(user, appInfo.packageName)) {return false;}final AndroidPackage pkg = mPackageManagerInternal.getPackage(appInfo.packageName);if (pkg == null) {// Should not happen, but we shouldn't be failing if it doesreturn false;}// If app does not have any default enabled launcher activity or any permissions,// the app can legitimately have no icon so we do not show the synthetic activity.return requestsPermissions(pkg) && hasDefaultEnableLauncherActivity(appInfo.packageName);
}

根据以上源码,可以发现该机制有个全局设置开关,并且有多种情况可以不受该机制限制。因此总结出如下解决方案:

  • 若是你的APP有adb权限或ROOT权限,可以直接修改这个全局开关,修改命令如下:
adb shell settings put global show_hidden_icon_apps_enabled 0
  • 或者你的APP有设备管理员权限
  • 或者你的APP是系统APP
  • 或者你的APP没有任何默认启动入口
  • 或者你的APP没有请求任何权限
  • 或者你的APP涉及到Managed profile(这个具体不太清楚怎么用)
  • 或者你的APP是Xposed模块,可以直接注入系统服务拦截相关API,或者注入可以修改系统设置的APP(比如:设置)直接修改这个开关
  • 或者你是系统源码开发者,可以直接修改该处代码即可
  • 其它更多还未探索出的方式(比如利用某些逻辑漏洞)…

参考

  • Android hide/unhide app icon programmatically

Android Studio gradle 没依赖成功 但不报错 只有调用时会报红

可以单独运行一下依赖任务,就会出现错误信息了

在这里插入图片描述

Empty SMPTE 2094-40 data 报错问题

搜索源码定位到打印日志位置:SharedMetadata#151

临时解决方案

借用AS 新版Logcat 过滤语法进行过滤即可,过滤语法如下

-tag:gralloc4 

即排除掉tag为gralloc4的日志

【远程USB】VirtualHere 指定IP(Android 远程开发优雅连接调试设备)

一般我们Android远程调试一般直接是adb connect ip:port,但是呢,这个很不方便,你还需要配置wifi USB调试,但是远程USB就不一样了,连接远程设备就像连接本地设备一样操作,直接adb device就可以看见设备了,不用什么adb connect和wifi USB调试。

而远程USB工具,当然就推荐VirtualHere了,VirtualHere使用起来真香,局域网内,直接安装运行就行了,不需要任何操作(当然了,试用版同一时间仅限一台设备,不过对于个人使用,这足够了,需要时再切换即可,反正又不绑定设备),但互联网的话就不能这么操作了,毕竟互联网这么多IP,它怎么知道是哪个对不对,所以需要我们手动指定IP,正文开始…



服务端若是在服务器运行的,那就不用动了,若是在本地运行的话,就需要做内网穿透了,这里推荐FRP,简单方便开源,具体这里就不展开讲了;

然后在客户端中,在USB Hubs上右键菜单选择Specify Hubs…

在这里插入图片描述
然后点击add添加,在新窗口输入你的ip和port即可
在这里插入图片描述
之后等待USB hubs下出现新设备即可
在这里插入图片描述

若是出现问题,可以通过

telnet ip port

命令,看看是否可以正常连接,若不能正常连接,检查防火墙是否拦截了

Frida使用技巧

命令行

Frida命令

  • 指定IP和Port:-H 127.0.0.1:27042
  • 强制重启应用:-f
  • 重启后直接运行应用:–no-pause
  • 注入指定包名(必须):com.xxxxx.xxx
  • 注入指定进程ID(与上面二选一):pid
  • 调试js代码:–debug --runtime=v8

具体参考Here,其中代码方式开启调试测试不太管用,具体待分析

  • 指定要加载的js文件路径(必须):-l path_to_js

接入Google Admob

官方Demo

Here

填坑

  • 1.The ad request was successful, but no ad was returned due to lack of ad inventory
    参考Here

1.未关联应用商店应用,在应用设置里添加应用ID,也就是包名,且在google play,或者其支持的应用商店上架
2.填充率低,采用中介模式,具体参考Here
2.1.查看国内支持的广告源,参考Here

  • 2.需要上车才能显示Ad

参考

  • 1.https://groups.google.com/g/google-admob-ads-sdk/c/Vy5itxLq704/m/F0OtHn4gBAAJ

App支付功能实现及踩坑

支付宝支付实现

1.正规支付实现
前提条件:

1. 企业或个体工商户可申请,且账号通过支付宝实名认证审核
2. 需提供真实有效的营业执照,且支付宝账户名称需与营业执照主体一致;
3. 提供APP名称或产品说明文档,开发者与支付宝账户名称不一致需提供开发合作协议。
(您可以提供产品介绍文档或者手机demo .apk .doc .docx .pdf格式,内容要求包含产品说明、接口使用场景、资费说明等(文件大小不超过5M)如果已经在appstore、googleplay、豌豆荚上架,可不提供文档demo,直接提供应用名称)

现在企业和个体工商户的办理,某宝应该都可以搜到,我咨询了卖家,说是需要对公账户,
这里写图片描述
对公账户具体意思呢,卖家就说是上面第二个条件.
还是不太明白,我又上网百度了下:
这里写图片描述
看来百度,也百度不到什么,试试用谷歌吧
这里写图片描述
终于让我找到了,看来还是谷歌大法好,百度真是越做越垃圾了!
看来要对公账号,就等于要申请一个公司啊,那还是算了,想起那一大堆文件和流程就害怕!只能等待以后有一定资金了直接某宝找人代办吧

2.非正规实现
1.还是使用个人支付账号,然后服务端后台(或个人电脑端)不断监听付款记录,当匹配到特定备注的支付记录时就进行相应处理!
2.使用第三方代理支付,就是把支付交给已经得到支付宝认证的第三方支付商,这样的话的确是最方便的,不做任何处理就可以得到支付宝的正规支付功能,缺点就是肯定会收手续费了,当然收手续费很正常,毕竟人家提供了服务嘛,另一个缺点就是这个服务商是否可信,毕竟人家后台怎么处理你根本不知道,同样的这种服务商都一个共同的最大的缺点—不稳定,就是一个开发者的App支付若是被投诉,肯定会影响到这个服务商,在支付宝那边就相当于这个服务商被投诉,若投诉多了,那这个服务商也就挂了!

微信支付实现

1.正规实现
这里写图片描述
同样需要企业认证,其开发者认证也不是很容易
这里写图片描述
仅认证个开发者就要300元,还仅是一年的!
这里写图片描述
还是需要企业,算了,放弃!
2.非正规实现
还在研究中…

参考

1.支付宝收款流程

DcseTBS获取设备ID原理

这款工具的就不说了,这不是文章的重点,今天我们要研究一下他的获取设备唯一ID的原理。
其实它获取设备唯一ID的方法跟别人的没啥区别,
实现代码:

TelephoneManager tm=TelephoneManager.getSystemService(Context.TELEPHONE_SERVICE);
tm.getDeviceId();

代码非常的简单,所以破解它也非常的简单,用xposed模块hook即可修改,或者直接反编译修改也可以。

但重点不在这里,而是破解之后的情况,它的每个设备ID不充值是仅能使用一天的,所以我破解它的方法是让他每次返回随机设备ID,这样不就可以破解了,可是事实不是这样的,并没有破解(其实后来才知道已经破解了),每次打开显示错误,真是让我纠结了半天,以为他是用了反射或者通过其他方式获取了设备ID,或者把设备ID存储在了内存卡,通过我的验证,最后发现都没有,这就让我懵逼了,难道使用了我不知到的方法,就在我准备放弃的时候,我想到了一个被我忽略的地方,那就是我的网络IP地址,并且发现有时候错误的信息并不一样,到最后我终于发现了问题的关键点
原来是当它获取到新的设备ID时,并不会第一时间就出现试用信息,而是出现错误信息,并让你重启,正常在没破解的情况下,在第二次进入时就会出现试用信息了,但是当我们把它破解之后,每次获取的都是随机的设备ID,也就是当第二次重启时,又获取的是新的设备ID,这是又需要再重启一次,可是再获取一次又是新的设备ID,这样造成的结果就是永远不会出现试用信息!
既然明白了问题,那破解也就简单了,只要在每次过了试用期后,再返回一个新的设备ID即可!
真是一个非常巧妙地防止被破解的方法!

破解后的截图

这里写图片描述
不要频繁重置ID,一天一次即可,设置了新的ID后直接点击“明天再提示”,就会等到明天这个时候会自动提示更换新ID,这时候再设置一个新ID即可。

破解后的APK

看有这多人要,我就直接发出来吧!
下载地址:https://download.csdn.net/download/qq_26914291/10383983
【注】该Apk仅供研究测试用,用作它用造成的一切损失一概与本人无关 !

总结

1.破解遇到问题,一定要仔细观察错误的信息,或许原因就藏在那些之中!
2.其实往往看似复杂的东西其实很简单!

代码混淆

初级混淆

使用proGuard进行代码混淆

1.参考教程:Android开发者指南(9) —— ProGuard
2.混淆模板:Android proguard-rules.pro 混淆模板
3.[Android 代码混淆 选项说明(https://blog.csdn.net/jjwwmlp456/article/details/44977721)

几个可以增加混淆强度的命令:

#将所有类放到跟目录下
-flattenpackagehierarchy#使用唯一的类成员名称
-useuniqueclassmembernames

几个可以增加混淆强度的字典
1.https://github.com/ihbing/AndroidObfuseDictionary

几个使用时需要注意的命令:
1.-assumenosideeffects使用时一定不要加-dontoptimize才起作用

# 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用
# 记得proguard-android.txt中一定不要加-dontoptimize才起作用
-assumenosideeffects class android.util.Log {public static int v(...);public static int i(...);public static int w(...);public static int d(...);public static int e(...);
}

[注]
1.eclipse只有将项目导出时才会进行混淆
2.1 proguard.config=proguard-project.txt//采用相对路径配置,直接读取项目根目录下proguard-project.txt文件
2.2 proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt//采用绝对路径

使用proGuard-GUI进行手动混淆

使用AndResGuard进行资源混淆

参考教程:AndResGuard集成笔记

增加7z压缩

参考教程:Android项目集成AndResGuard资源混淆两种方式
参考教程:https://github.com/shwenzhang/AndResGuard/blob/master/doc/how_to_work.zh-cn.md

注意点

1.如何打开Gradle中的Task任务?
这里写图片描述

进阶混淆

使用StringFog对字符串Base64加密

参考教程:https://github.com/MegatronKing/StringFog

将字符串混淆成byte字节码

如下图
这里写图片描述
参考教程:https://github.com/ihbing/obfuseSmaliText

高阶混淆

修改proGuard工具的混淆字符

[注]AndroidStudio的自身proGuard混淆工具目录D:\Program Files\Android\Android Studio\gradle\m2repository\net\sf\proguard\proguard-base\D:\Program Files\Android\Android Studio\gradle\m2repository\net\proguard-base\

用无效代码对抗jadx&jd-gui

 //添加无效代码,对抗jadx & jd-guiboolean qwerty21345hjdnjd = false;while (qwerty21345hjdnjd) {switch (1) {case 1:while (qwerty21345hjdnjd) {try {Throwable throwable=new Throwable();Throwable cause = throwable.getCause();} catch (NullPointerException e) {} finally {}}break;}}

参考

1.Android资源混淆工具
2.proGuard混淆笔记
3.Android代码混淆技术总结(一)
4.apk在线反混淆

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

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

相关文章

探秘Java的Map集合:键值映射的奇妙世界

文章目录 1. 单列集合 vs. 双列集合2. Map接口&#xff1a;键与值的契约3. 深入探索HashMap3.1 特性与构造方法3.2 常用方法3.3 遍历HashMap 4. 美妙的LinkedHashMap 在Java编程中&#xff0c;集合是不可或缺的重要部分&#xff0c;它为我们提供了各种数据结构和算法的实现。其…

【ES】笔记-箭头函数的实践于应用场景

箭头函数的实践于应用场景 需求-1 点击 div 2s后颜色变成[粉色]从数组中返回偶数的元素 需求-1 点击 div 2s后颜色变成[粉色] html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport…

element-ui树形表格,左边勾选,右边显示选中的数据-功能(如动图)

功能如图 功能需求 表格树形表格勾选数据&#xff0c;右边显示对应勾选的数据内容&#xff0c;选中客户&#xff0c;自动勾选所有的店铺(子级)&#xff0c;选中其中一个店铺&#xff0c;自动勾选上客户(父级)&#xff0c;同时会存在只有客户&#xff08;下面没有子级的情况&am…

【数据结构】栈及其实现

目录 1.栈的概念及结构 2.栈的实现 2.1栈结构定义 2.2初始化及销毁 2.3插入数据 2.4删除数据 2.5访问栈顶数据 2.6判断是否为空栈 2.7计算栈的大小 3.8访问栈中所有数据 1.栈的概念及结构 栈&#xff1a;栈是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插…

Oracle 开发篇+Java通过共享模式访问Oracle数据库

标签&#xff1a;共享服务器进程、shared server process释义&#xff1a;shared server process是Oracle的一种数据库连接技术&#xff0c;类似的还有专用模式和DRCP ★ 数据库配置 alter system set shared_server_sessions1 scopespfile; alter system set max_shared_serv…

FPGA优质开源项目 - UDP RGMII千兆以太网

本文介绍一个FPGA开源项目&#xff1a;UDP RGMII千兆以太网通信。该项目在我之前的工作中主要是用于FPGA和电脑端之间进行图像数据传输。本文简要介绍一下该项目的千兆以太网通信方案、以太网IP核的使用以及Vivado工程源代码结构。 Vivado 的 Tri Mode Ethernet MAC IP核需要付…

谈谈Spring与字节码生成技术

Java程序员几乎都了解Spring。 它的IoC&#xff08;依赖反转&#xff09;和AOP&#xff08;面向切面编程&#xff09;功能非常强大、易用。而它背后的字节码生成技术&#xff08;在运行时&#xff0c;根据需要修改和生成Java字节码的技术&#xff09;就是一项重要的支撑技术。 …

协程(一)单机--》并发--》协程

目录 一 协程的概述1.1 并行与并发1.2 线程1.3 新的思路1.4 Goroutine 二 第一个入门程序 一 协程的概述 我查看了网上的一些协程的资料&#xff0c;发现每个人对协程的概念都不一样&#xff0c;但是我认可的一种说法是&#xff1a;协程就是一种轻量级的线程框架&#xff08;K…

uniapp软键盘谈起遮住输入框和头部被顶起的问题解决

推荐&#xff1a; pages.json中配置如下可解决头部被顶起和表单被遮住的问题。 { "path": "pages/debug/protocol/tagWord", "style": { "app-plus": { "soft…

基于Containerd容器引擎和kubeadm工具部署K8sv1.26.3

kubernetes master节点及node节点各核心组件的功能概述 master节点主要组件概述 master节点主要是k8s的控制节点&#xff0c;在master节点上主要有三个组件必不可少&#xff0c;apiserver、scheduler和controllermanager&#xff1b;etcd是集群的数据库&#xff0c;是非常核心的…

关于Postman如何配置随请求携带token

文章目录 一些吐槽实际应用 一些吐槽 首先吐槽一下 postman官网的文档说明&#xff0c;真是乱七八糟&#xff0c;一点都不清晰&#xff0c;能不能好好写用户手册啊&#xff08;比如把用户都当作初始小白&#xff09; 然后吐槽一下网上铺天盖地让我写js脚本应用全局access toke…

Oracle 知识篇+会话级全局临时表在不同连接模式中的表现

标签&#xff1a;会话级临时表、全局临时表、幻读释义&#xff1a;Oracle 全局临时表又叫GTT ★ 结论 ✔ 专用服务器模式&#xff1a;不同应用会话只能访问自己的数据 ✔ 共享服务器模式&#xff1a;不同应用会话只能访问自己的数据 ✔ 数据库驻留连接池模式&#xff1a;不同应…