weico居然是开机启动

本文解析了Weico应用中的WeicoNewMsgPullService服务,包括其启动机制、如何监听屏幕状态变化及如何检查应用是否处于前台。同时,还详细介绍了如何通过反编译工具Jadx来分析该服务的工作原理。
摘要由CSDN通过智能技术生成

原来所谓的开机启动就是在zygote启动之后,孵化出来的进程啊,我杀了几次都会重新启动。

这个Service一直在响,打开应用管理器,发现是这个Service。
//TODO nexus的截图。

先用apktool初步解压出apk的内容

apktool解压出来的是smali文件,这里我们暂时不关注,先关注它解析后的AndroidManifest.xml,毕竟这里面列举出了所有可能会用到的组件(如果不列出某组件却要用到的话,应用就会崩溃)。

AndroidManifest.xml文件中找这个Service。

上Jadx

Jadx主要是反编译dex文件的,而扔给它一个apk文件也是可以的,但是会占用很大的内存,因为还需要解析一些res目录下的图片等资源文件。
所以在上Jadx之前,先用zip等解压缩工具直接将apk解压出来,得到了两个dex文件。class.dexclass2.dex,这是由于方法数达到了上限65535而导致的分包现象,即不得不用两个dex来装所有编译后的class文件。参考:http://www.wjdiankong.cn/android%E5%85%B3%E4%BA%8Edex%E6%8B%86%E5%88%86multidex%E6%8A%80%E6%9C%AF%E8%AF%A6%E8%A7%A3/

然后分别将这两个dex放到Jadx中,并使用--deobf参数进行反混淆(个人比较喜欢使用,对于一些类名方法名等被混淆的代码使用反混淆之后可以方便查找然后重命名)
有两种方式,一种是命令行方式:

方法一

# 使用jadx将两个dex文件反编译然后放到当前的jadx目录下(若没有则创建),并将标准输出和标准错误重定向到/dev/null,即不显示输出和错误信息。
$ jadx class.dex -d ./jadx --deobf  1>/dev/null 2>/dev/null
$ jadx class.dex -d ./jadx --deobf  1>/dev/null 2>/dev/null

然后反编译后的java源码就导出到./jadx目录下了。

方法二

另外一种方式是

$ jadx-gui class.dex

然后记得按下反混淆的选项。等左下角的进度条完成之后,点击save as gradle project。


找到其全名为com.weico.international.service.WeicoNewMsgPullService.java
先找到它的onCreate()方法,毕竟这个方法会在首次启动改Service比调用的。

registerScreenNotify()

查看registerScreenNotify()的定义,将三个Intent

android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
android.intent.action.USER_PRESENT
# 这三个Intent是用来获取用户的交互状态的。
# 参考:
# https://developer.android.com/reference/android/content/Intent.html </br>
注意 SCREEN_ON和SCREEN_OFF是无法在AndroidManifest.xml中注册的,必须用Java代码手动注册

加入到mReceiver中,并注册mReceiver这个广播接收者

而mReceiver是是一个自定义的BroadcastReceiver


从代码中看,作者认为只要匹配到action为android.intent.action.USER_PRESENT时,才将mUserIsScreenLock设置为false。

每个用户隔一段时间重新开始使用手机时,首先按电源键点亮屏幕,紧接着解锁。android.intent.action.USER_PRESENT就是解锁时发出的intent.
注意这个action只能有系统发出,是在用户唤醒机器的时候才会发出这种action.

参考:
http://blog.csdn.net/heikefangxian23/article/details/46888645
然后通过isProcessFrontground()方法判断进程名为com.weico.international的进程是否处于UI前台。

// com.weico.international.service.WeicoNewMsgPullService.java
    private boolean isProcessFrontground() {
        return ActivityUtils.isForeAppProcess(this);
    }


// com/weico/international/utility/ActivityUtils.java 
    public static boolean isForeAppProcess(Context context) {
        return isForeAppProcess(context, context.getApplicationInfo().processName);
    }

    public static boolean isForeAppProcess() {
        return isForeAppProcess(WApplication.cContext, "com.weico.international");
    }

    private static boolean isForeAppProcess(Context context, String processName) {
       List<RunningAppProcessInfo> runningTaskList = ((ActivityManager) context.getSystemService("activity")).getRunningAppProcesses();
        if (runningTaskList == null || runningTaskList.isEmpty()) {
            return false;
        }
        for (RunningAppProcessInfo appProcessInfo : runningTaskList) {
            if (processName.contentEquals(appProcessInfo.processName)) {
            // importance为100其实就是处于进程处于前台UI界面,正在与用户交互。参考:https://developer.android.com/reference/android/app/ActivityManager.RunningAppProcessInfo.html#IMPORTANCE_FOREGROUND
                if (appProcessInfo.importance == 100) {
                    return true;
                }
                return false;
            }
        }
        return false;
    }

即当用户处于weico界面前台时,则清除(cancel)掉这四种通知。

// com/weico/international/model/sina/UnreadMsg.java
public class UnreadMsg extends BaseType {
...
    public static final int NEW_AT_ME_COMMENT_IDENTIFIER = 10000005;
    public static final int NEW_AT_ME_IDENTIFIER = 10000001;
    public static final int NEW_COMMENT_IDENTIFIER = 10000002;
    public static final int NEW_DM_IDENTIFIER = 10000003;
    public static final int NEW_FOLLOWER_IDENTIFIER = 10000004;

然后就是执行一个每10s fetch一下未读消息的Runnable了。

看一下这个
而这个mToStopRunnable变量只在onDestroy()方法中设置为true,从而结束Ruannble的运行。

// com.weico.international.service.WeicoNewMsgPullService.java
...
    public void onDestroy() {
        super.onDestroy();
        // 注销广播
        unregisterReceiver(this.mReceiver);
        // 停止Runnable
        this.mToStopRunnable = true;
        // shutdown掉ExecutorService es好习惯
        this.es.shutdown();
    }

src/main/java/com/weico/international/service/WeicoNewMsgPullService.java

    private void fetchUnreadCount() {
        Account mAccount = AccountsStore.getCurAccount(); // 这里命名为什么要加m?
        if (mAccount != null) {
            this.mUnreadMsgApi = new UnreadMsgAPI(mAccount.curAccessToken());
            this.mUnreadMsgApi.getUnreadMsg(mAccount.getUser().getIdstr(), new C04802());
            return;
        }
        compareUnreadCount(new UnreadMsg());
        stopSelf();  // 会执行onDestroy()
    }

src/main/java/com/weico/international/manager/accounts/AccountsStore.java

    public static Account getCurAccount() {
        if (curAccount != null || getAccountSize() == 0) {
            return curAccount;
        }
        return (Account) accountList.get(0);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值