参考相关应用
- 华为市场 -> 充电有喜2.0.1
- 网络查找 -> 充电有喜1.0.0 http://www.xz7.com/downinfo/609008.html
- 反编译app有个文字漏洞,找到 来福充电宝 https://sj.qq.com/appdetail/com.evenhaexplo.courte
需要解决的问题
- 电源插拔注册
- 为什么需要悬浮窗权限
- 后台弹窗实现
- 锁屏显示权限
最后的总结
- 在壁纸Fragment中监听电源插拔
- 有个后台弹出权限,保证弹出来
- android.permission.BIND_NOTIFICATION_LISTENER_SERVICE 有一定程度的保活(弱)
- (不在项目中)android-keeplive
- AndroidKeepAlive
组件化总结
- ARouter
- BinderHook(https://github.com/pinggle/binderHook)
Android插件化原理解析——Hook机制之Binder Hook https://weishu.me/2016/02/16/understand-plugin-framework-binder-hook/
其他相关
- DSBridge-Android https://github.com/wendux/DSBridge-Android
- ijkplayer播放 ‘tv.danmaku.ijk.media:ijkplayer-java:0.8.8’
- stringfog 字符串加密
说明:
- 定向分析,只找到了上面的总结相关
- 还需要非定向分析(即一个包一个包找,需要花些时间)
步骤
使用apkHelper分析基本信息
com.dwelliembos.equivo
1. 用jadx和GDA打开apk,分析基本信息
jadx
GDA
通过frida脚本down下内存中的dex
frida -U -f com.xxx.xxx.xxx -l dupDex.js
在相对应的目录下找到生成的dex
分析监听电源插拔,电量变化
追溯到CommonWebFragment
想找CommonWebFragment出现在哪里,目测应该是通用的一个
找到Activity -> com.luoli.oubin.web.CommonWebAct
问题:
-
CommonWebAct是什么时候调用的
-
作用是什么,UI是否透明
有注册
<activity android:name="com.luoli.oubin.web.CommonWebAct" ></activity>
package com.luoli.oubin.web.js.BaseWebInterface;
CommonWebView
com.dwelliembos.equivo.oOOO00o
找到一些加载的URL
o0o000Oo.o0o000Oo.o0OO0O0.o0OO0O0
无意间找到首页
找到几个网址:
https://bd.chengyudatiaozhan.com/update_frontend_service/index?infoId=8d6bb4fe325e4261ae8f161db4e0c88b
https://bd.chengyudatiaozhan.com/update_frontend_service/index?infoId=e8287ca4a20d4d1abb247857338b85a8
用户协议 https://docs.qq.com/doc/DQXB5bFZCQWNPVlZz
隐私协议 https://docs.qq.com/doc/DQVJFQVhDd3dNY1pG
MainActivity
this.setContentView(0x7f0c0025);
多个Fragment
- 首页 new o00oooo(),
主页的主内容
0x7f0c006
.field public static final fragment_home:I = 0x7F0C0066
重点在Reclerview
但是,并没有找到CommonWebFragment相关的?
-
壁纸 new oOOO00o(),
-
福气 new oo0o0oO(),
-
我的 new o00o0oO0(
回到正题,找到CommonWebFragment
在壁纸Fragment中监听了插拔信息
找到了 com.air.wallpaper.realpage.details.view.real.ChargeWallPaperActivity@e9b63bf
android.permission.BIND_NOTIFICATION_LISTENER_SERVIC
Android 通知监听服务、NotificationListenerService使用方式(详细步骤+源码) 原创
https://blog.51cto.com/u_15117645/5669824
Android NotificationListenerService通知监听服务使用
https://www.jb51.net/article/267863.htm
<service android:name="com.test.rommatch.service.NotificationService" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter >
<action android:name="android.service.notification.NotificationListenerService" ></action>
</intent-filter>
</service>
悬浮窗权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" ></uses-permission>
Android app打开系统界面设置悬浮窗权限
https://blog.csdn.net/niuba123456/article/details/120197603
不同机型判断悬浮窗权限
android window浮窗 安卓10悬浮窗适配 转载
https://blog.51cto.com/u_16213635/7853449
后台弹出壁纸
-
找监听电源插拔ACTION_POWER_CONNECTED
-
跳转到LazyWallpaperActivity
-
清单文件中
<activity android:name="com.whiaz.wall.LazyWallpaperActivity" android:launchMode="3" android:screenOrientation="1" android:configChanges="0x000004a0" ></activity>
-
WallpaperLayoutManager
自定义的 -
LazyWallpaperActivity的界面
-
R$layout.activity_wallpaper_details
-
设置壁纸界面
-
弹出ChargeWallPaperActivity
应该是组件化策略Arouter
-
找到Arouter的这个
-
静态代码跳转的设置壁纸界面, 但弹出框是ChargeActivity。两个不一样。有问题??
-
LazyWallpaperActivity
找保活相关
com.dwelliembos.equivo.App
在v2.0.1中
解决思路
1. 都需要什么权限
来福充电宝~~~
找到权限弹窗LazyWxShowPermissionActivity
adb shell dumpsys activity top
跳转到悬浮窗权限
public interface abstract o000o000 // class@001156 from classes.dex
{
default static void o0OO0O0(Activity p0,int p1){
if (Build$VERSION.SDK_INT >= 23) {
Intent intent = new Intent("android.settings.action.MANAGE_OVERLAY_PERMISSION");
intent.setData(Uri.parse("package:"+p0.getPackageName()));
p0.startActivityForResult(intent, p1);
}
return;
}
}
PERMISSION_HAD_GRANTED_BACKGROUND
android 10+从后台启动 Activity 的限制
https://blog.csdn.net/xiaoyantan/article/details/128401740
android 系统权限授权 安卓授权管理
https://blog.51cto.com/u_12228/6575401
class LazyWxShowPermissionActivity$o0OO0O0 implements oOO0oo00 // class@001123 from classes.dex
{
final LazyWxShowPermissionActivity o0OO0O0;
void LazyWxShowPermissionActivity$o0OO0O0(LazyWxShowPermissionActivity p0){
this.o0OO0O0 = p0;
super();
}
public void o0OO0O0(){
LazyWxShowPermissionActivity.o0Ooo0(this.o0OO0O0).oOO0oo00.setSelected(false);
oo0oOO0.oOOOooOO("开启后台弹出权限失败,请重试");
}
public void oOO0oo00(){
ActivityManager systemServic = this.o0OO0O0.getSystemService("activity");
boolean b = (Build$VERSION.SDK_INT >= 28)? systemServic.isBackgroundRestricted(): true;
if (oOOo0OO0.o00o0oOO()) {
LazyWxShowPermissionActivity.o0Ooo0(this.o0OO0O0).oOO0oo00.setSelected(true);
oOOo0000.o0OO0O0.o0o000Oo("PERMISSION_HAD_GRANTED_BACKGROUND", true);
return;
}else if(ooooooO0.o0o0OOoO()){
LazyWxShowPermissionActivity.o0Ooo0(this.o0OO0O0).oOO0oo00.setSelected(true);
oOOo0000.o0OO0O0.o0o000Oo("PERMISSION_HAD_GRANTED_BACKGROUND", true);
}
if (!b) {
LazyWxShowPermissionActivity.o0Ooo0(this.o0OO0O0).oOO0oo00.setSelected(true);
oOOo0000.o0OO0O0.o0o000Oo("PERMISSION_HAD_GRANTED_BACKGROUND", true);
}else {
LazyWxShowPermissionActivity.o0Ooo0(this.o0OO0O0).oOO0oo00.setSelected(false);
ToastUtils.oo00O00o("开启后台弹出权限失败,请重试");
}
return;
}
}
Android 判断后台运行权限是否开启
https://blog.51cto.com/u_16213369/7650688
Android 取消后台运行限制
https://www.jianshu.com/p/1e75b9fb71d2
workmanager
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
如何设置壁纸
❌只是一个弹窗,并不是概念上的壁纸功能,所以后台弹窗是很重要的
VideoWallpaperService
com.whiaz.wall.VideoWallpaperService
<service android:name="com.whiaz.wall.VideoWallpaperService" android:permission="android.permission.BIND_WALLPAPER" >
<intent-filter >
<action android:name="android.service.wallpaper.WallpaperService" ></action>
</intent-filter>
<meta-data android:name="android.service.wallpaper" android:resource="@xml/wallpaper" ></meta-data>
</service>
保活库AndroidKeepAlive
https://github.com/fgkeepalive/AndroidKeepAlive
Android进程保活实战经验(已经上线使用)
https://blog.51cto.com/u_16353097/8775791
https://github.com/08carmelo/android-keeplive
https://github.com/08carmelo/android-keeplive
不同的手机有不同的策略
不断地点进去,都可以找到相应的手机型号
锁屏显示弹窗
How to enable ‘show in lock screen’ permission in andriod
https://stackoverflow.com/questions/60478065/how-to-enable-show-in-lock-screen-permission-in-andriod
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
public static void goToNotificationSettings(Context context) {
Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts(SCHEME, context.getPackageName(), null));
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("app_package", context.getPackageName());
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("app_package", context.getPackageName());
intent.putExtra("app_uid", context.getApplicationInfo().uid);
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + context.getPackageName()));
} else {
return;
}
context.startActivity(intent);
}
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_NOTIFICATION_POLICY) != PackageManager.PERMISSION_GRANTED) {
goToNotificationSettings(getActivity());
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
创建简单的 widget
https://developer.android.com/develop/ui/views/appwidgets?hl=zh-cn#lockscreen
Android开发艺术探索》第八章笔记.md
https://github.com/francistao/LearningNotes/blob/aa04b68b728a3505077f8d2a1ce931b758367b54/Part5/ReadingNotes/%E3%80%8AAndroid%E5%BC%80%E5%8F%91%E8%89%BA%E6%9C%AF%E6%8E%A2%E7%B4%A2%E3%80%8B%E7%AC%AC%E5%85%AB%E7%AB%A0%E7%AC%94%E8%AE%B0.md?plain=1#L17
监听插入电源
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
object ChargingMonitor {
val TAG = ChargingMonitor::class.simpleName
private val callbacks = CopyOnWriteArrayList<Callback>()
private val intentFilter = IntentFilter().apply {
addAction(Intent.ACTION_POWER_CONNECTED)
addAction(Intent.ACTION_POWER_DISCONNECTED)
priority = 1000
}
init {
MyApp.application.registerReceiver(object : BroadcastReceiver {
override fun onReceive(context: Context, intent: Intent) {
Log.i(TAG, "ChargingMonitor 有广播到了 action=${intent.action}!")
if (intent.action == Intent.ACTION_POWER_CONNECTED) {
callbacks.forEach { callback -> callback.onCharging(true) }
} else {
callbacks.forEach { callback -> callback.onCharging(false) }
}
}
}, intentFilter)
Log.i(TAG, "注册监听电源插拔成功!")
}
fun init() = Unit
fun addCallback(callback: Callback) {
callbacks.add(callback)
}
fun removeCallback(callback: Callback) {
callbacks.remove(callback)
}
interface Callback {
fun onCharging(isCharging: Boolean)
}
}
AndroidManifest.xml文件中的权限可以一一分析
<uses-permission android:name="android.permission.INTERNET" ></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" ></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" ></uses-permission>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" ></uses-permission>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" ></uses-permission>
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" ></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" ></uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE" ></uses-permission>
<uses-permission android:name="android.permission.GET_TASKS" ></uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK" ></uses-permission>
<uses-permission android:name="android.permission.SET_WALLPAPER" ></uses-permission>
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" ></uses-permission>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" ></uses-permission>
<uses-permission android:name="android.permission.REORDER_TASKS" ></uses-permission>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" ></uses-permission>
<uses-permission android:name="android.permission.READ_SETTINGS" ></uses-permission>
<uses-permission android:name="android.permission.WRITE_SETTINGS" ></uses-permission>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" ></uses-permission>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" ></uses-permission>
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" ></uses-permission>
<uses-permission android:name="oppo.permission.OPPO_COMPONENT_SAFE" ></uses-permission>
<uses-permission android:name="com.huawei.permission.external_app_settings.USE_COMPONENT" ></uses-permission>
MessengerUtils.java
https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/src/main/java/com/blankj/utilcode/util/MessengerUtils.java
很多使用的方法
https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/README-CN.md
额外分析
资料
多个dex文件合成方法
https://zhuanlan.zhihu.com/p/681385679
光环助手
com.sensorsdata.analytics.android.sdk.remote.SensorsDataRemoteManagerDebug