You are on page 1of 7

9/30/2015

Developmenttutorialrovo89/XposedBridgeWikiGitHub
Thisrepository Search

Explore

Features

Enterprise

rovo89 / XposedBridge

Pricing

Watch

Signup

Star

151

Developmenttutorial

792

Signin

Fork

312

rovo89editedthispageonAug13,201411revisions

Alright..youwanttolearnhowyoucancreateanewmoduleforXposed?Thenreadthis
tutorial(orlet'srathercallit"extensiveessay")andlearnhowtoapproachthis.This
includesnotonlythetechnical"createthisfileandinsert...",butalsothethinkingbehind

Pages

Home

it,whichisthestepwherevalueiscreatedandforwhichyoureallyneedtounderstand

Developmenttutorial

whatyoudoandwhy.Ifyoufeellike"TLDR",youcanjustlookatthefinalsourcecode

Helpers

andreadthe"MakingtheprojectanXposedmodule"chapter.Butyouwillgetabetter

Replacingresources

understandingifyoureadthewholetutorial.Youwillsavethetimespentforreadingthis
laterbecauseyoudon'thavetofigureeverythingoutyourself.

Clonethiswikilocally
https://github.com/rovo89/XposedBridge.wiki.git

Themodificationsubject

CloneinDesktop

YouwillrecreatetheredclockexamplethatcanbefoundatGithubaswell.Itincludes
changingthecolorofthestatusbarclocktoredandaddingasmiley.I'mchoosingthis
examplebecauseitisarathersmall,buteasilyvisiblechange.Also,itusessomeofthe
basicmethodsprovidedbytheframework.

HowXposedworks
Beforebeginningwithyourmodification,youshouldgetaroughideahowXposedworks
(youmightskipthissectionthoughifyoufeeltoobored).Hereishow:
Thereisaprocessthatiscalled"Zygote".ThisistheheartoftheAndroidruntime.Every
applicationisstartedasacopy("fork")ofit.Thisprocessisstartedbyan/init.rcscript
whenthephoneisbooted.Theprocessstartisdonewith/system/bin/app_process,
whichloadstheneededclassesandinvokestheinitializationmethods.
ThisiswhereXposedcomesintoplay.Whenyouinstalltheframework,anextended
app_processexecutableiscopiedto/system/bin.Thisextendedstartupprocessaddsan
additionaljartotheclasspathandcallsmethodsfromthereatcertainplaces.For
instance,justaftertheVMhasbeencreated,evenbeforethemainmethodofZygotehas
beencalled.Andinsidethatmethod,wearepartofZygoteandcanactinitscontext.
Thejarislocatedat/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar
anditssourcecodecanbefoundhere.LookingattheclassXposedBridge,youcansee
themainmethod.ThisiswhatIwroteaboutabove,thisgetscalledintheverybeginning
oftheprocess.Someinitializationsaredonethereandalsothemodulesareloaded(Iwill
comebacktomoduleloadinglater).

Methodhooking/replacing
WhatreallycreatesthepowerofXposedisthepossibilityto"hook"methodcalls.When
youdoamodificationbydecompilinganAPK,youcaninsert/changecommandsdirectly
whereveryouwant.However,youwillneedtorecompile/signtheAPKafterwardsandyou
canonlydistributethewholepackage.WiththehooksyoucanplacewithXposed,you
can'tmodifythecodeinsidemethods(itwouldbeimpossibletodefineclearlywhatkindof
changesyouwanttodoinwhichplace).Instead,youcaninjectyourowncodebeforeand
aftermethods,whicharethesmallestunitinJavathatcanbeaddressedclearly.
https://github.com/rovo89/XposedBridge/wiki/Developmenttutorial

1/7

9/30/2015

Developmenttutorialrovo89/XposedBridgeWikiGitHub

XposedBridgehasaprivate,nativemethodhookMethodNative.Thismethodis
implementedintheextendedapp_processaswell.Itwillchangethemethodtypeto
"native"andlinkthemethodimplementationtoitsownnative,genericmethod.That
meansthateverytimethehookedmethodiscalled,thegenericmethodwillbecalled
insteadwithoutthecallerknowingaboutit.Inthismethod,themethod
handleHookedMethodinXposedBridgeiscalled,passingovertheargumentstothemethod

call,thethisreferenceetc.Andthismethodthentakescareofinvokingcallbacksthat
havebeenregisteredforthismethodcall.Thosecanchangetheargumentsforthecall,
changeinstance/staticvariables,invokeothermethods,dosomethingwiththeresult...or
skipanythingofthat.Itisveryflexible.
Ok,enoughtheory.Let'screateamodulenow!

Creatingtheproject
Amoduleisnormalapp,justwithsomespecialmetadataandfiles.Sobeginwithcreating
anewAndroidproject.Iassumeyouhavealreadydonethisbefore.Ifnot,theofficial
documentationisquitedetailed.WhenaskedfortheSDK,Ichose4.0.3(API15).I
suggestyoutrythisaswellanddonotstartexperimentsyet.Youdon'tneedtocreatean
activitybecausethemodificationdoesnothaveanyuserinterface.Afteransweringthat
question,youshouldhaveablankproject.

MakingtheprojectanXposed
module
Nowlet'sturntheprojectintosomethingloadedbyXposed,amodule.Severalstepsare
requiredforthis.

AndroidManifest.xml
ThemodulelistintheXposedInstallerlooksforapplicationswithaspecialmetadataflag.
YoucancreateitbygoingtoAndroidManifest.xml=>Application=>ApplicationNodes(at
thebottom)=>Add=>MetaData.Thenameshouldbexposedmoduleandthevalue
true.Leavetheresourceempty.Thenrepeatthesameforxposedminversion(see

below)andxposeddescription(averyshortdescriptionofyourmodule).TheXMLsource
willnowlooklikethis:
<?xmlversion="1.0"encoding="utf8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="de.robv.android.xposed.mods.tutorial"
android:versionCode="1"
android:versionName="1.0">
<usessdkandroid:minSdkVersion="15"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<metadata
android:name="xposedmodule"
android:value="true"/>
<metadata
android:name="xposeddescription"
android:value="Easyexamplewhichmakesthestatusbarclockredandaddsasmiley
<metadata
android:name="xposedminversion"
android:value="30"/>
</application>
</manifest>

https://github.com/rovo89/XposedBridge/wiki/Developmenttutorial

2/7

9/30/2015

Developmenttutorialrovo89/XposedBridgeWikiGitHub

XposedBridgeApi.jar
Next,maketheXposedBridgeAPIknowntotheproject.Youcandownload
XposedBridgeApi<version>.jarfromthefirstpostofthisXDAthread.Copyitintoa

subfoldercalledlib.ThenrightclickonitandselectBuildPath=>AddtoBuildPath.
The<version>fromthefilenameistheoneyouinsertasxposedminversioninthe
manifest.
MakesurethattheAPIclassesarenotincluded(butonlyreferenced)inyour
compiledAPK,otherwiseyouwillgetanIllegalAccessError.Filesinthelibs(with
"s")folderareautomaticallyincludedbyEclipse,sodon'tputtheAPIfilethere.

Moduleimplementation
Nowyoucancreateaclassforyourmodule.Mineisnamed"Tutorial"andisinthe
packagede.robv.android.xposed.mods.tutorial:
packagede.robv.android.xposed.mods.tutorial;
publicclassTutorial{
}

Forthefirststep,wewilljustdosomeloggingtoshowthatthemodulewasloaded.A
modulecanhaveafewentrypoints.Whichone(s)youchoosedependsonthewhatyou
wanttomodify.YoucanhaveXposedcallafunctioninyourmodulewhentheAndroid
systemboots,whenanewappisabouttobeloaded,whentheresourcesforanappare
initialisedandsoon.
Abitfurtherdownthistutorial,youwilllearnthatthenecessarychangesneedtobedone
inonespecificapp,solet'sgowiththe"letmeknowwhenanewappisloaded"entry
point.AllentrypointsaremarkedwithasubinterfaceofIXposedMod.Inthiscase,it's
IXposedHookLoadPackagewhichyouneedtoimplement.It'sactuallyjustonemethod
withoneparameterthatgivesmoreinformationaboutthecontexttotheimplementing
module.Inourexample,let'slogthenameoftheloadedapp:
packagede.robv.android.xposed.mods.tutorial;
importde.robv.android.xposed.IXposedHookLoadPackage;
importde.robv.android.xposed.XposedBridge;
importde.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
publicclassTutorialimplementsIXposedHookLoadPackage{
publicvoidhandleLoadPackage(finalLoadPackageParamlpparam)throwsThrowable{
XposedBridge.log("Loadedapp:"+lpparam.packageName);
}
}

Thislogmethodwritesthemessagetothestandardlogcat(tagXposed)andto
/data/data/de.robv.android.xposed.installer/log/debug.log`(whichiseasilyaccessiblevia
theXposedInstaller).

assets/xposed_init
TheonlythingthatisstillmissingnowisahintforXposedBridgewhichclassescontain
suchentrypoints.Thisisdoneviaafilecalledxposed_init.Createanewtextfilewith
thatnameintheassetsfolder.Inthisfile,eachlinecontainsonefullyqualifiedclass
name.Inthiscase,thisisde.robv.android.xposed.mods.tutorial.Tutorial.

https://github.com/rovo89/XposedBridge/wiki/Developmenttutorial

3/7

9/30/2015

Developmenttutorialrovo89/XposedBridgeWikiGitHub

Tryingitout
Saveyourfiles.ThenrunyourprojectasAndroidapplication.Asthisisthefirsttimeyou
installit,youneedtoenableitbeforeyoucanuseit.OpentheXposedInstallerappand
makesureyouhaveinstalledtheframework.Thengotothe"Modules"tab.Youshould
findyourappinthere.Checktheboxtoenableit.Thenreboot.Youwillnotseea
differenceofcourse,butifyoucheckthelog,youshouldseesomethinglikethis:
LoadingXposed(forZygote)...
Loadingmodulesfrom/data/app/de.robv.android.xposed.mods.tutorial1.apk
Loadingclassde.robv.android.xposed.mods.tutorial.Tutorial
Loadedapp:com.android.systemui
Loadedapp:com.android.settings
...(manymoreappsfollow)

Voil!Thatworked.YounowhaveanXposedmodule.Itcouldjustbeabitmoreuseful
thanwritinglogs...

Exploringyourtargetandfindinga
waytomodifyit
Ok,sonowbeginsthepartthatcanbeverydifferentdependingonwhatyouwanttodo.If
youhavemoddedAPKsbefore,youprobablyknowhowtothinkhere.Ingeneral,youfirst
needtogetsomedetailsabouttheimplementationofthetarget.Inthistutorial,thetarget
istheclockinthestatusbar.Ithelpstoknowthatthestatusbarandlotsofotherthingsare
partoftheSystemUI.Solet'sbeginoursearchthere.
Possibilityone:Decompileit.Thiswillgiveyoutheexactimplementation,butitishardto
readandunderstandbecauseyougetsmaliformat.Possibilitytwo:GettheAOSP
sources(e.g.hereorhereandlookthere.ThiscanbequitedifferentfromyourROM,but
inthiscaseitisasimilaroreventhesameimplementation.IwouldlookatAOSPfirstand
seeifthatisenough.IfIneedmoredetails,lookattheactualdecompiledcode.
Youcanlookforclasseswith"clock"intheirnameorcontainingthatstring.Otherthings
tolookforareresourcesandlayoutused.IfyoudownloadedtheofficialAOSPcode,you
canstartlookinginframeworks/base/packages/SystemUI.Youwillfindquiteafewplaces
where"clock"appears.Thisisnormalandindeedtherewillbedifferentwaystoimplement
amodification.Keepinmindthatyoucan"only"hookmethods.Soyouhavetofinda
placewhereyoucaninsertsomecodetodothemagiceitherbefore,afterorreplacinga
method.Youshouldhookmethodsthatareasspecificaspossible,notonesthatare
calledthousandsoftimestoavoidperformanceissuesandunintendedsideeffects.
Inthiscase,youmightfindthatthelayoutres/layout/status_bar.xmlcontainsa
referencetoacustomviewwiththeclasscom.android.systemui.statusbar.policy.Clock.
Multipleideasmightcometoyourmindnow.Thetextcolorisdefinedviaa
textAppearanceattribute,sothecleanestwaytochangeitwouldbetochangethe

appearancedefinition.However,thethisisnotpossibletochangestyleswiththeXposed
frameworkandprobablywon'tbe(it'stoodeepinnativecode).Replacingthelayoutfor
thestatusbarwouldbepossible,butanoverkillforthesmallchangeyouaretryingto
make.Instead,lookatthisclass.ThereisamethodcalledupdateClock,whichseemsto
becalledeveryminutetoupdatethetime:
finalvoidupdateClock(){
mCalendar.setTimeInMillis(System.currentTimeMillis());
setText(getSmallTime());
}

https://github.com/rovo89/XposedBridge/wiki/Developmenttutorial

4/7

9/30/2015

Developmenttutorialrovo89/XposedBridgeWikiGitHub

Thatlooksperfectformodificationsbecauseitisaveryspecificmethodwhichseemsto
betheonlymeansofsettingthetextfortheclock.Ifweaddsomethingaftereverycallto
thismethodthatchangesthecolorandthetextoftheclock,thatshouldwork.Solet'sdo
it.
Forthetextcoloralone,thereisanevenbetterway.Seetheexamplefor"Modifying
layouts"on"Replacingresources".

Usingreflectiontofindandhooka
method
Whatdowealreadyknow?WehaveamethodupdateClockinclass
com.android.systemui.statusbar.policy.Clockthatwewanttointercept.Wefoundthis

classinsidetheSystemUIsources,soitwillonlybeavailableintheprocessforthe
SystemUI.Someotherclassesbelongtotheframeworkandareavailableeverywhere.If
wetriedtogetanyinformationandreferencestothisclassdirectlyinthe
handleLoadPackagemehod,thiswouldfailbecauseitisthewrongprocess.Solet's

implementaconditiontoexecutecertaincodeonlywhenaspecifiedpackageisaboutto
beloaded:
publicvoidhandleLoadPackage(LoadPackageParamlpparam)throwsThrowable{
if(!lpparam.packageName.equals("com.android.systemui"))
return;
XposedBridge.log("weareinSystemUI!");
}

Usingtheparameter,wecaneasilycheckifweareinthecorrectpackage.Oncewe
verifiedthat,wegetaccesstotheclassesinthatpackageswiththeClassLoaderwhichis
alsoreferencedfromthisvariable.Nowwecanlookforthe
com.android.systemui.statusbar.policy.ClockclassanditsupdateClockmethodandtell

XposedBridgetohookit:
packagede.robv.android.xposed.mods.tutorial;
importstaticde.robv.android.xposed.XposedHelpers.findAndHookMethod;
importde.robv.android.xposed.IXposedHookLoadPackage;
importde.robv.android.xposed.XC_MethodHook;
importde.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
publicclassTutorialimplementsIXposedHookLoadPackage{
publicvoidhandleLoadPackage(finalLoadPackageParamlpparam)throwsThrowable{
if(!lpparam.packageName.equals("com.android.systemui"))
return;
findAndHookMethod("com.android.systemui.statusbar.policy.Clock",lpparam.classLoader,
@Override
protectedvoidbeforeHookedMethod(MethodHookParamparam)throwsThrowable
//thiswillbecalledbeforetheclockwasupdatedbytheoriginalmethod
}
@Override
protectedvoidafterHookedMethod(MethodHookParamparam)throwsThrowable{
//thiswillbecalledaftertheclockwasupdatedbytheoriginalmethod
}
});
}
}

findAndHookMethodisahelperfunction.Notethestaticimport,whichisautomatically

addedifyouconfigureitasdescribedinthelinkedpage.ThismethodlooksuptheClock
https://github.com/rovo89/XposedBridge/wiki/Developmenttutorial

5/7

9/30/2015

Developmenttutorialrovo89/XposedBridgeWikiGitHub

classusingtheClassLoaderfortheSystemUIpackage.ThenitlooksfortheupdateClock
methodinit.Iftherewereanyparameterstothismethod,youwouldhavetolistthetypes
(classes)oftheseparametersafterwards.Therearedifferentwaystodothis,butasour
methoddoesn'thaveanyparameters,let'sskipthisfornow.Asthelastargument,you
needtoprovideanimplementationoftheXC_MethodHookclass.Forsmallermodifications,
youcanuseaanonymousclass.Ifyouhavemuchcode,it'sbettertocreateanormal
classandonlycreatetheinstancehere.Thehelperwillthendoeverythingnecessaryto
hookthemethodasdescribedabove.
TherearetwomethodsinXC_MethodHookthatyoucanoverride.Youcanoverridebothor
evennone,butthelattermakesabsolutelynosense.Thesemethodsare
beforeHookedMethodandafterHookedMethod.It'snottoohardtoguessthattheare

executedbefore/aftertheoriginalmethod.Youcanusethe"before"methodto
evaluate/manipulatetheparametersofthemethodcall(viaparam.args)andevenprevent
thecalltotheoriginalmethod(sendingyourownresult).The"after"methodcanbeused
todosomethingbasedontheresultoftheoriginalmethod.Youcanalsomanipulatethe
resultatthispoint.Andofcourse,youcanaddyourowncodewhichshouldbeexecuted
exactlybefore/afterthemethodcall.
Ifyouwanttoreplaceamethodcompletely,havealookatthesubclass
XC_MethodReplacementinstead,whereyoujustneedtooverride
replaceHookedMethod.

XposedBridgekeepsalistofregisteredcallbacksforeachhookedmethod.Thosewith
highestpriority(asdefinedinhookMethod)arecalledfirst.Theoriginalmethodhas
alwaysthelowestpriority.SoifyouhavehookedamethodwithcallbacksA(priohigh)
andB(priodefault),thenwheneverthehookedmethodiscalled,thecontrolflowwillbe
this:A.before>B.before>originalmethod>B.after>A.after.SoAcouldinfluencethe
argumentsBgetstosee,whichcouldfurtherchangethembeforepassingthemon.The
resultoftheoriginalmethodcanbeprocessedbyBfirst,butAhasthefinalwordwhatthe
originalcallergets.

Finalsteps:Executeyourowncode
before/afterthemethodcall
Alright,youhavenowamethodthatiscalledeverytimetheupdateClockmethodis
called,withexactlythatcontext(i.e.you'reintheSystemUIprocess).Nowlet'smodify
something.
Firstthingtocheck:DowehaveareferencetotheconcreteClockobject?Yeswehave,
it'sintheparam.thisObjectparameter.Soifthemethodwascalledwith
myClock.updateClock(),thenparam.thisObjectwouldbemyClock.

Next:Whatcanwedowiththeclock?TheClockclassisnotavailable,youcan'tcast
param.thisObjecttoclass(don'teventryto).HoweveritinheritsfromTextView.Soyou

canusemethodslikesetText,getTextandsetTextColoronceyouhavecastedthe
ClockreferencetoTextView.Thechangesshouldbedoneaftertheoriginalmethodhas

setthenewtime.Asthereisnothingtodobeforethemethodcall,wecanleaveoutthe
beforeHookedMethod.Callingthe(empty)"super"methodisnotnecessary.

Sohereisthecompletesourcecode:
packagede.robv.android.xposed.mods.tutorial;
importstaticde.robv.android.xposed.XposedHelpers.findAndHookMethod;
importandroid.graphics.Color;
importandroid.widget.TextView;
importde.robv.android.xposed.IXposedHookLoadPackage;
importde.robv.android.xposed.XC_MethodHook;

https://github.com/rovo89/XposedBridge/wiki/Developmenttutorial

6/7

9/30/2015

Developmenttutorialrovo89/XposedBridgeWikiGitHub

importde.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
publicclassTutorialimplementsIXposedHookLoadPackage{
publicvoidhandleLoadPackage(finalLoadPackageParamlpparam)throwsThrowable{
if(!lpparam.packageName.equals("com.android.systemui"))
return;
findAndHookMethod("com.android.systemui.statusbar.policy.Clock",lpparam.classLoader,
@Override
protectedvoidafterHookedMethod(MethodHookParamparam)throwsThrowable{
TextViewtv=(TextView)param.thisObject;
Stringtext=tv.getText().toString();
tv.setText(text+":)");
tv.setTextColor(Color.RED);
}
});
}
}

Behappyabouttheresult
Nowinstall/startyourappagain.AsyouhavealreadyenableditintheXposedInstaller
whenyoustarteditthefirsttime,youdonotneedtodothatagain,rebootingisenough.
However,youwillwanttodisabletheredclockexampleifyouwereusingit.Bothusethe
defaultpriorityfortheirupdateClockhandler,soyoucannotknowwhichonewillwin(it
actuallydependsonthestringrepresentationofthehandlermethod,butdon'trelyon
that).

Conclusion
Iknowthatthistutorialwasverylong.ButIhopeyoucannownotonlyimplementagreen
clock,butalsosomethingcompletelydifferent.Findinggoodmethodstohookisamatter
ofexperience,sostartwithsomethingrathereasy.Tryusingthelogfunctionsalotinthe
beginningtomakesurethateverythingiscalledwhenyouexpectit.Andnow:Havefun!

2015GitHub,Inc. Terms Privacy Security Contact Help

https://github.com/rovo89/XposedBridge/wiki/Developmenttutorial

Status API Training Shop Blog About Pricing

7/7