前言
Xposed開源框架網(wǎng)上有很多的資源,其使用原理和使用方法有很多的資料了二汛,但是為了加深自己對Xpose原理的理解婿崭,還是參考大神的自己理解總結(jié)了下,其原理通過替換/system/bin/app_process程序來控制Zygote進程肴颊,在app_process進程啟動時會加載XposeBridge.jar這個jar包氓栈,從而完成對Zygote進程和虛擬機的劫持。
在Android系統(tǒng)中婿着,應(yīng)用程序進程都是由Zygote進程孵化出來的授瘦,而Zygote進程是由Init進程啟動的。Zygote進程在啟動時會創(chuàng)建一個Dalvik虛擬機實例竟宋,每當它孵化一個新的應(yīng)用程序進程時提完,都會將這個Dalvik虛擬機實例復(fù)制到新的應(yīng)用程序進程里面去,從而使得每一個應(yīng)用程序進程都有一個獨立的Dalvik虛擬機實例丘侠。這也是Xposed選擇替換app_process的原因徒欣。
Zygote進程在啟動的過程中,除了會創(chuàng)建一個Dalvik虛擬機實例之外蜗字,還會將Java運行時庫加載到進程中來打肝,以及注冊一些Android核心類的JNI方法來前面創(chuàng)建的Dalvik虛擬機實例中去脂新。注意,一個應(yīng)用程序進程被Zygote進程孵化出來的時候粗梭,不僅會獲得Zygote進程中的Dalvik虛擬機實例拷貝争便,還會與Zygote一起共享Java運行時庫。這也就是可以將XposedBridge這個jar包加載到每一個Android應(yīng)用程序中的原因断医。XposedBridge有一個私有的Native(JNI)方法hookMethodNative滞乙,這個方法也在app_process中使用。
XsharePreference的使用
相信很多人都使用過Xposed框架去hook某個應(yīng)用編寫出很多模塊鉴嗤,在編寫hook模塊的時候往往我們都涉及到數(shù)據(jù)保存酷宵,比如hook某個應(yīng)用方法的開關(guān)控制,我們需要將開關(guān)的狀態(tài)保存躬窜,當Xposed執(zhí)行hook到這個方法是會讀取開關(guān)的狀態(tài)浇垦,對于保存數(shù)據(jù)而言有很多種方式,如讀寫文件荣挨、創(chuàng)建數(shù)據(jù)庫保存男韧,使用SharePreference保存等等。我今天所介紹的是Xposed中封裝的XSharePreference的Api的使用默垄。
使用方法
方式一 使用 XSharedPreferences(String packageName)獲取
我們知道SharePrefernce實際上是對應(yīng)在/data/data/<Package Name>/shared_prefs/<Package Name>_preferences.xml文件此虑。里面按鍵值對的形式存放。XSharedPreferences做的工作實際上就是根據(jù)<Package Name>自己去解析這個文件口锭,然后讀出數(shù)據(jù)存放在一個HashMap當中朦前。
構(gòu)造方法源碼
public XSharedPreferences(String packageName) {
this(packageName, packageName + "_preferences");
}
通過構(gòu)造方法可以看出我們在設(shè)置SharePrefernece的第一個參數(shù)時后面還需要加上"_preference"。
保存數(shù)據(jù)
SharedPreferences mSharedPreferences = getActivity().getSharedPreferences(getPackageName() + "_preferences", Activity.MODE_WORLD_READABLE);
SharedPreferences.Editor mEditor = mSharedPreferences.edit();
mEditor.putBoolean(PreferenceUtils.AUTO_ALL, (Boolean) newValue).commit();
mEditor.putString(PreferenceUtils.REPLY_CONTENT,(String)newValue).commit();
注意在設(shè)置SharePrefernce的模式是設(shè)置成
Activity.MODE_WORLD_READABLE鹃操,只有這樣XSharePreference才能訪問韭寸。但是當Xposed中使用XSharepreference在7.0系統(tǒng)上時會遇到安全異常,XsharePreference會失效荆隘,此時最好的解決方法是使用ContentProvider代替使用恩伺。
數(shù)據(jù)訪問
XSharedPreferences intance = new XSharedPreferences("com.ydscience.fakemomo");
方式二 使用public XSharedPreferences(String packageName, String prefFileName) (推薦使用)
XSharePreference的第二種初始化構(gòu)造方法源碼為
public XSharedPreferences(String packageName, String prefFileName) {
mFile = new File(Environment.getDataDirectory(), "data/" + packageName + "/shared_prefs/" + prefFileName + ".xml");
mFilename = mFile.getAbsolutePath();
startLoadFromDisk();
}
對比兩個構(gòu)造方法而言,第一個初始化完成后繼續(xù)調(diào)用第二個初始化構(gòu)造函數(shù)椰拒,但是對比而言個人還是喜歡第二種晶渠,使用簡單清晰。
保存數(shù)據(jù)
SharedPreferences mSharedPreferences = getActivity().getSharedPreferences("config", Activity.MODE_WORLD_READABLE);
SharedPreferences.Editor mEditor = mSharedPreferences.edit();
mEditor.putBoolean(PreferenceUtils.AUTO_ALL, (Boolean) newValue).commit(); mEditor.putString(PreferenceUtils.REPLY_CONTENT,(String)newValue).commit();
數(shù)據(jù)訪問
在數(shù)據(jù)訪問時封裝了一個類PreferenceUtils類燃观,完整代碼為
public class PreferenceUtils {
public static final String AUTO_ALL ="auto_all";
public static final String REPLY_CONTENT ="reply_content";
public static final String REPLY_ORDER ="reply_order";
public static final String REPLY_ROBOT ="reply_robot";
public static final String REPLY_DESCRIBE ="reply_describe";
private static XSharedPreferences intance = null;
public static XSharedPreferences getIntance(){
if (intance == null){
intance = new XSharedPreferences("com.ydscience.fakemomo","config");
intance.makeWorldReadable();
}else {
intance.reload();
}
return intance;
}
public static boolean openAll(){
return getIntance().getBoolean(AUTO_ALL,false);
}
public static String replyContent(){
return getIntance().getString(REPLY_CONTENT,"請設(shè)置自動回復(fù)內(nèi)容");
}
}