Xposed Hook ohne Reboot

B

burgerohnealles

Fortgeschrittenes Mitglied
18
Servus.

Kann man nicht irgendwie die Hooks ohne Reboot aktualisieren? Ich meine nen Modul gesehen zu haben, was das kann ...
Jedes mal das Handy neuzustarten nervt auf Dauer nämlich ziemlich ..

Danke schon mal :)
 
Kommt darauf an, was Du meinst mit 'Einen Hook ohne Reboot' zu aktivieren:

Ein Modul ohne Reboot zu aktivieren geht nicht, da die Module alle beim Starten des Systems aktiviert werden, wenn der sogenannte 'AppProcess' gestartet wird.

Das was ein Xposed-Modul aber tut (sprich, welche Apps und welche derer Methoden das Modul hooket), das kann der Entwickler des Moduls so implementieren, dass es zur Laufzeit des Gerätes aktiviert oder deaktiviert werden kann. Das muss dann so implementiert werden, dass die Methode auf jeden Fall gehooket wird, aber der Hook selbst entweder nichts tut (inaktiv ist) oder aber seine Aufgabe ausführt (aktiv ist). Details kannst Du hier sehen: [Tutorial] Xposed Module selbst erstellen - Abschnitt: Der Settings-Service: Kommunikation mit dem Modul

Wenn aber manche Module dieses nicht zur Laufzeit aktivieren können, muss das nicht unbedingt an einer schlechten Implementierung des Moduls liegen, sondern kann auch einfach eine bewusste Entscheidung sein, da es gewaltige Performance-Auswirkungen haben kann, sehr viele Hooks zu setzen, auch wenn der Hook selbst inaktiv ist.
 
Zuletzt bearbeitet:
So hab ich das nicht gemeint. Ich entwickle selber ein Xposed-Modul und muss dabei ja nach jeder Änderung das Handy neustarten.
Versuche ich außerhalb vom eigentlichen Modul in der App auf Xposed-Funktion zuzugreifen bekomme ich ein NoClassDefFoundError. So kann ich also keine Hooks z.B. nach der Installation setzten. Gibts da irgendeine Möglichkeit?
 
Genau diese Frage war in dem von mir verlinkten Tutorial behandelt.
 
Wenn ich das jetzt auf die schnelle richtig gesehen habe, gehts in deinem Tutorial darum, wie das Xposed-Modul mit der Konfigurations-App kommuniziert.
Aber wenn ich die App aktualisiert habe, muss diese erst durch die XposedBrige geladen werden, was ja normalerweise nur beim Neustart des System geschieht (oder hab ich da nen Denkfehler?). Und das will ich eben ohne Reboot machen. Evtl könnte man ein zweites Xposed-Modul schreiben, welches XposedBridge hooked (falls das überhaupt geht) und von dort aus andere Module ohne Reboot laden könnte?
 
Nee, das Verändern des Moduls als solches kann auf Grund des Prinzips von Xposed nicht gehen.

Dazu muss man folgendes wissen:

Wenn Android gestartet wird, wir einmal ein Prozess namens AppProcess gestartet. Dieser dient als Vorlage für jede einzelne App, die auf diesem Gerät gestartet wird, in dem für jede zu startende App eine Kopie des Ursprungs-'AppProcess'-Prozesses angelegt wird.

Das Xposed-Framework klinkt sich in diesen ersten Prozess ein und lädt alle Module. Jeder weitere App Prozess ist nur eine Kopie und bekommt damit alle Module mit kopiert. Das ist damit nicht mehr wirklich veränderbar.
[doublepost=1460895566,1460895264][/doublepost]Nachtrag:

Man könnte natürlich ein 'Alternatives Xposed-Framework' konstruieren, dass das Laden der Module dynamischer gestaltet, als es das 'Original-Xopsed-Framework' tut, aber diese Dynamik würde einen ganz enorm negativen Einfluss auf die Performance haben. Deswegen hat sich Rovo damals für dieses 'Inital-Lade-Verhalten' entschieden.
[doublepost=1460897568][/doublepost]Noch ein Nachtrag:

Kiwi++Soft schrieb:
Das Xposed-Framework klinkt sich in diesen ersten Prozess ein

Einklinken ist hier vielleicht ein falscher Ausdruck:

Eigentlich besteht der Hauptbestandteil des Xposed-Frameworks aus einer alternativen Implementierung des Binaries dieses AppProcesses
 
Zuletzt bearbeitet:
Hm okey danke.
Dann würde mich aber genauer interessieren, wo das "Problem" ist. Denn:
Das setzten von Hooks klappt immer (hab ich ausprobiert; gehe davon aus, da es nach 30 Sekunden Wartezeit immer noch klappt). Jetzt wird man nur daran gehindert, dass man beim Zugriff auf das XposedFramework von der "normalen" App aus ein NoClassDefFoundError bekommt.
Wenn man die Klasse (das Xposed-Modul) wie in der XposedBridge mittels
ClassLoader mcl = new PathClassLoader(apk, BOOTCLASSLOADER);
lädt sollte es aber klappen, oder nicht? Wenn ich von der normalen App aus
getClass().getClassLoader().getParent()
aufrufe, bekomme ich ein java.lang.BootClassLoader, von dem Xposed-Modul aus aber,
dalvik.system.PathClassLoader[DexPathList[zip file "/data/data/.../XposedBridge.jar"],...]
.. was auch erklärt, warum ich von der "normalen" App nicht auf die XposedBridge zugreifen kann.

Wie kann ich hier eigentlich Code einfügen, so als Text sieht das nämlich blöd aus.
 
Zum Code-Tag:

Untitled.png

Das Setzen oder Löschen von Hooks aus dem bestehenden Code ist natürlich möglich, aber Überladen von Klassen, die bereits geladen wurden, nicht. Dazu kannst Du Dich am besten mal mit dem Thema 'Classloader-Hierarchie' unter Java beschäftigen, welchen Impact das Laden von bereits geladenen Klassen hat. Stichpunkt: Warum sollte ein Classloader keine Klasse definieren, die sein Parent-Classloader bereits kennt.

Und Du solltest Dir bewusst sein, dass eine Konfigurations-App ein eigener einzelner Prozess ist, während Dein Modul in jedem AppProzess am Laufen ist
 
Zuletzt bearbeitet:
Kiwi++Soft schrieb:
Thema 'Classloader-Hierarchie' unter Java beschäftigen
Ja genau, hab das bis jetzt nie gebraucht, muss mich da wohl mal einlesen. Daher ist das, was ich momentan mache eher mehr Herumprobiererei.

Aber hab noch ein anderes Problem bezüglich Xposed. Bei folgendem Code hätte ich z.B.
Code:
XposedModule-><init>
mTest #0: 0
mTest #1: 1
im Log erwartet, bekomme aber
Code:
XposedModule-><init>
mTest #0: 0
mTest #1: 0
... warum?
Code:
// ... package & imports
public class XposedModule implements IXposedHookLoadPackage {

    private int mTest = 0;


    public XposedModule () {
        XposedBridge.log("XposedModule-><init>");
    }


    @Override
    public synchronized void handleLoadPackage (XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (lpparam.packageName.equals("ein.paket")) {
            XposedBridge.log("mTest #0: " + mTest);
            mTest++;
        } else if (lpparam.packageName.equals("ein.anderes.paket")) {
            XposedBridge.log("mTest #1: " + mTest);
            mTest++;
        }
}
 
Ich schreibe gerne Tutorials oder gebe allgemeine Erklärungen. Den Code eines Entwicklers zu pflegen, sehe ich aber als Aufgabe des Entwicklers und halte mich dazu immer heraus, tut mir Leid.
 
Sorry aber das verstehe ich jetzt nicht .. der Code von mir im vorherigen Post verdeutlicht nur ein allgemeines Problem, für das ich gerne eine Erklärung hätte ..
 
Ich lese mich nicht in anderer Entwickler Code ein, um rauszufinden, was darin los ist, auch wenn es noch so offensichtlich ist. Das ist m.E. Sache des Entwicklers selbst.

Sorry, wenn ich es nicht schaffe, es nachvollziehbar zu erklären, aber ich bin hier raus.
 
Hm okey. Wenn ich das Problem in Worte fasse, hilfst du dann weiter?
 
OK, ich sage es Dir woran es liegt:

Jede App, die gestartet wir, landet in ihrem eigenen Memory-Bereich.

Daher wird bei:

Code:
        if (lpparam.packageName.equals("ein.paket")) {
            XposedBridge.log("mTest #0: " + mTest);
            mTest++;
        }

die Variable mTest im Speicherbereich der App "ein.paket" erst ausgegeben (ist also 0) und dann erhöht, aber bei

Code:
        else if (lpparam.packageName.equals("ein.anderes.paket")) {
            XposedBridge.log("mTest #1: " + mTest);
            mTest++;
        }

die Variable mTest aus dem Speicherbereich der App "ein.anderes.paket" ausgegeben (ist also immer noch 0) und dann erhöht.

Daher wirst Du bei diesem Konstrukt immer nur 0 ausgegeben bekommen.
 
Okey danke. Das hatte mich zuerst verwundert, da ja nur eine Instanz existiert (daher der log im Konstruktor).

Wie kann ich Daten im einem gemeinsamen Speicherbereich ablegen bzw. nach was muss ich suchen um darüber mehr zu lesen? Wenn du dazu gute deutsche/englische Artikel kennst, kannst du diese gerne verlinken.
 
Da die Module beim initialisieren des ersten AppProcess geladen werden (siehe oben), wird der Constructor nur einmal durchlaufen. Da aber für jede App eine Kopie des AppProcess geklont wird, hat dann dennoch jede App einen eigenen Speicherbereich.

Zur Kommunikation zwischen des einzelnen Instanzen sollte man unter Android die Mechanismen von Android verwenden (Broadcast Receiver)
 
Okey alles klar danke :)
 

Ähnliche Themen

5
Antworten
22
Aufrufe
1.420
590239
5
CrazyC
Antworten
6
Aufrufe
1.055
CrazyC
CrazyC
M
  • maksimilian
Antworten
6
Aufrufe
1.557
maksimilian
M
Zurück
Oben Unten