Android 控制 ContentProvider的創(chuàng)建

序言

隨著app隱私政策的收緊,現(xiàn)在不經(jīng)過用戶同意,就收集敏感信息的行為一旦被檢測出來。很容易造成app下架。但是有些SDK的初始化是通過注冊ContentProvider實現(xiàn)自動調(diào)用其onCreate()方法,來實現(xiàn)無感初始化的。如果SDK在ContentProvider中獲取了敏感信息,又沒有提供控制方法。我們就很被動。于是我花了點時間研究了怎么hook contentProvider的創(chuàng)建。讓其在用戶同意后再初始化。

方案1

聲明在清單文件中的ContentProvider 會在應用啟動后就創(chuàng)建。具體是在 ActivityThread的handleBindApplication方法中。<font color='red'>(以下截圖為Android 30的ActivityThread)</font>


在這里插入圖片描述

具體就在這一句


在這里插入圖片描述

installContentProviders實現(xiàn)如下


在這里插入圖片描述

最終是通過AppComponentFactory的instantiateProvider方法創(chuàng)建。


在這里插入圖片描述

在這里插入圖片描述

而AppComponentFactory是Android 28以后系統(tǒng)提供給我們的一個hook的工廠類。可以通過清單文件指定,在這里面可以hook 所有組件的初始化。


在這里插入圖片描述

這么指定


在這里插入圖片描述

但是在Android 28以下,比如這個截圖是Android 25.沒有這類,ContentProvider直接通過反射獲得。無法通過該類來修改。


在這里插入圖片描述

最終方案

為了兼容性,考慮如下方案。在調(diào)用installContentProviders前,如果這個data里面的providers為空豈不是不會走installContentProviders方法了嗎。


在這里插入圖片描述

這個data 是一個AppBindData類型,通過handleBindApplication方法的參數(shù)傳入。會保存到ActivityThread的 mBoundApplication 字段中。


在這里插入圖片描述

于是就可以通過獲取這個mBoundApplication 字段中的providers 來保存要初始化的provider。再講providers置為空即可。到了用戶同意以后,再去通過反射調(diào)用ActivityThread的installContentProviders方法即可。


在這里插入圖片描述

hook時機

這個時機只有Application的attachBaseContext方法中。該方法會比installContentProviders提前執(zhí)行。

最后的代碼App中

public class MyApp extends Application {

    static MyApp app;

    /**
    *用戶同意
    */
    public static void agree(Action action) {
        HookUtil.initProvider(app);
        action.doAction();
    }

    public interface Action {
        void doAction();
    }


    @Override
    protected void attachBaseContext(Context base) {
        app = this;
        try {
            HookUtil.attachContext();
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.attachBaseContext(base);
    }
}

HookUtil

package com.zgh.testcontentprovider;

import android.content.Context;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;


/**
 * Created by zhuguohui
 * Date: 2021/9/13
 * Time: 11:23
 * Desc:
 */
public class HookUtil {

    private static Object providers;

    private static Method installContentProvidersMethod;
    private static Object currentActivityThread;

    /*
    *用戶同意后調(diào)用
    */
    public static void initProvider(Context context){
        try {
            installContentProvidersMethod.invoke(currentActivityThread,context,providers);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void attachContext() throws Exception {

        // 先獲取到當前的ActivityThread對象
        Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
        Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
        currentActivityThreadMethod.setAccessible(true);
        //currentActivityThread是一個static函數(shù)所以可以直接invoke,不需要帶實例參數(shù)
        currentActivityThread = currentActivityThreadMethod.invoke(null);

        hookInstallContentProvider(activityThreadClass);

    }

    private static void hookInstallContentProvider(Class activityThreadClass) throws Exception{
        Field appDataField = activityThreadClass.getDeclaredField("mBoundApplication");
        appDataField.setAccessible(true);
        Object appData= appDataField.get(currentActivityThread);
        Field providersField= appData.getClass().getDeclaredField("providers");
        providersField.setAccessible(true);
        providers = providersField.get(appData);
        //清空provider,避免有些sdk通過provider來初始化
        providersField.set(appData,null);

        installContentProvidersMethod = activityThreadClass.getDeclaredMethod("installContentProviders", Context.class, List.class);
        installContentProvidersMethod.setAccessible(true);
    }
}

搭配

搭配我之前寫的工具,可以更完美的實現(xiàn)用戶同意之前不初始化任何SDK的目標
通過攔截 Activity的創(chuàng)建 實現(xiàn)APP的隱私政策改造

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容