[Samsung Galaxy S 5 Unified Development] tdunham:
[Guide] How to add a SettingsObserver to your Rom

This will allow you to add a settings observer to existing smali.

Adding a settings observer allows you to create a real-time update to an existing mod such as colors and toggles so the modification takes effect instantly without any other user intervention such as reboots, etc.

Huge credits [MENTION=3771845]remuntada[/MENTION] for all the information included in this guide.

Probably the most utilized settings observer is present for the PhoneStatusBar.smali in SystemUI.apk so we will provide this as an example:

Also see here for example of how to add a RegObserver to QSPanel

RegObserver Guide

SettingsObserver Guide

SystemUI.apk smali edits:

\smali\com\android\systemui\statusbar\phone\PhoneStatusBar.smali

New code is in BLUE

# annotations
.annotation system Ldalvik/annotation/MemberClasses;
value = {
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$PmsBrightnessEnableObserver;,
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$EasyModeEnableObserver;,
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$BrightnessEnableObserver;,
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$BatteryTextObserver;,
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$DozeServiceHost;,
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$ShadeUpdates;,
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$FastColorDrawable;,
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$MyTicker;,
[COLOR="Blue"]Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;,[/COLOR]
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$H;,
Lcom/android/systemui/statusbar/phone/PhoneStatusBar$EmergencyModeObserver;,
}
.end annotation

Same smali, add new code in BLUE

The edit is about halfway into the smali. Make sure the values of the new code match the surrounding values. Note that after that :cond_0 there may be additional code in your smali. Just insert the new code where indicated.

.method public start()V
.
.
.
:cond_0[COLOR="Blue"]
new-instance v0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;

iget-object v1, p0, Lcom/android/systemui/statusbar/BaseStatusBar;->mHandler:Lcom/android/systemui/statusbar/BaseStatusBar$H;

invoke-direct {v0, p0, v1}, Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;-><init>(Lcom/android/systemui/statusbar/phone/PhoneStatusBar;Landroid/os/Handler;)V

invoke-virtual {v0}, Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;->observe()V[/COLOR]

new-instance v0, Lcom/android/systemui/statusbar/phone/PhoneStatusBarPolicy;

iget-object v1, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mContext:Landroid/content/Context;

iget-object v2, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mCastController:Lcom/android/systemui/statusbar/policy/CastControllerImpl;

invoke-direct {v0, v1, v2}, Lcom/android/systemui/statusbar/phone/PhoneStatusBarPolicy;-><init>(Landroid/content/Context;Lcom/android/systemui/statusbar/policy/CastController;)V

iput-object v0, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mIconPolicy:Lcom/android/systemui/statusbar/phone/PhoneStatusBarPolicy;

Same smali, add YOUR new method.

This is just an example method of a mod I added to change the dateview color that gets invoked from the SettingsObserver:

.method setDateTextViewColor()V
.locals 8

iget-object v1, p0, Lcom/android/systemui/SystemUI;->mContext:Landroid/content/Context;

invoke-virtual {v1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;

move-result-object v2

const-string v3, "pulldown_date_color"

const v1, -0x111112

invoke-static {v2, v3, v1}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I

move-result v7

iget-object v5, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mStatusBarWindow:Lcom/android/systemui/statusbar/phone/StatusBarWindowView;

const v6, 0x7f0d02b8 ## [COLOR="Green"]<public type="id" name="date_expanded"
[/COLOR]
invoke-virtual {v5, v6}, Lcom/android/systemui/statusbar/phone/StatusBarWindowView;->findViewById(I)Landroid/view/View;

move-result-object v4

check-cast v4, Landroid/widget/TextView;

invoke-virtual {v4, v7}, Landroid/widget/TextView;->setTextColor(I)V

return-void
.end method

Add the PhoneStatusBar$SettingsObserver.smali file already attached at the bottom of this post to the same folder as PhoneStatusBar.smali.

Now lets look in the PhoneStatusBar$SettingsObserver.smali to see how we made the changes to it.

Note the text in BLUE, this where we check for changes to the key string and in the second method is where the new method gets launched to update the view if changes have been detected to that key.

Note the text in GREEN, this is how you would add two more mods to the settings observer with two additional methods to invoke in PhoneStatusBar. They are only present as an example.

.class Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;
.super Landroid/database/ContentObserver;
.source "PhoneStatusBar.java"

# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
value = Lcom/android/systemui/statusbar/phone/PhoneStatusBar;
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x0
name = "SettingsObserver"
.end annotation

# instance fields
.field final synthetic this$0:Lcom/android/systemui/statusbar/phone/PhoneStatusBar;

# direct methods
.method constructor <init>(Lcom/android/systemui/statusbar/phone/PhoneStatusBar;Landroid/os/Handler;)V
.locals 0

iput-object p1, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;->this$0:Lcom/android/systemui/statusbar/phone/PhoneStatusBar;

invoke-direct {p0, p2}, Landroid/database/ContentObserver;-><init>(Landroid/os/Handler;)V

return-void
.end method

# virtual methods
.method observe()V
.locals 3

const/4 v2, 0x0

iget-object v1, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;->this$0:Lcom/android/systemui/statusbar/phone/PhoneStatusBar;

iget-object v1, v1, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mContext:Landroid/content/Context;

invoke-virtual {v1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;

move-result-object v0

[COLOR="Blue"]const-string v1, "pulldown_date_color"

invoke-static {v1}, Landroid/provider/Settings$System;->getUriFor(Ljava/lang/String;)Landroid/net/Uri;

move-result-object v1

invoke-virtual {v0, v1, v2, p0}, Landroid/content/ContentResolver;->registerContentObserver[/COLOR](Landroid/net/Uri;ZLandroid/database/ContentObserver;)V

[COLOR="Green"]const-string v1, "second_settings_key_goes_here"

invoke-static {v1}, Landroid/provider/Settings$System;->getUriFor(Ljava/lang/String;)Landroid/net/Uri;

move-result-object v1

invoke-virtual {v0, v1, v2, p0}, Landroid/content/ContentResolver;->registerContentObserver(Landroid/net/Uri;ZLandroid/database/ContentObserver;)V

const-string v1, "third_settings_key_goes_here"

invoke-static {v1}, Landroid/provider/Settings$System;->getUriFor(Ljava/lang/String;)Landroid/net/Uri;

move-result-object v1

invoke-virtual {v0, v1, v2, p0}, Landroid/content/ContentResolver;->registerContentObserver(Landroid/net/Uri;ZLandroid/database/ContentObserver;)V[/COLOR]

return-void
.end method

.method public onChange(Z)V
.locals 1

[COLOR="Blue"] iget-object v0, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;->this$0:Lcom/android/systemui/statusbar/phone/PhoneStatusBar;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->setDateTextViewColor()V
[/COLOR]
[COLOR="Green"]iget-object v0, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;->this$0:Lcom/android/systemui/statusbar/phone/PhoneStatusBar;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->setSecondMethod()V

iget-object v0, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar$SettingsObserver;->this$0:Lcom/android/systemui/statusbar/phone/PhoneStatusBar;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->setThirdMethod()V

[/COLOR] return-void
.end method

Modifying and adding a Settings Observer to most other smalis:

For smali where #annotations does not exist, add a new one right below the .source line like in this example. If #annotations already exist, add the line to #annotations as in the PhoneStatusBar.smali example above.

Note the highlighted text in RED, this path must match the smali you are working in (the green highlighted path).

.class public [COLOR="Green"]Lcom/android/incallui/dialpad/DialpadView[/COLOR];
.super Landroid/widget/LinearLayout;
.source "DialpadView.java"

[COLOR="Blue"]# annotations
.annotation system Ldalvik/annotation/MemberClasses;
value = {
[COLOR="Red"]Lcom/android/incallui/dialpad/DialpadView[/COLOR]$SettingsObserver;
}
.end annotation[/COLOR]

Search for either one of these methods:

.method public constructor <init>(Landroid/content/Context;Landroid/util/AttributeSet;)V

.method public constructor <init>(Landroid/content/Context;Landroid/util/AttributeSet;I)V

And add the new code in BLUE (and Red) before the return-void at the end of the method.

Note that the paths in RED have to match the smali you're working in.

Note that I had to increase the .locals value to accommodate the new entry which I did in this example.

.method public constructor <init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
[COLOR="Blue"].locals 3[/COLOR]

const/4 v0, 0x0

invoke-direct {p0, p1, p2, v0}, Lcom/android/incallui/dialpad/DialpadView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;I)V

[COLOR="blue"]new-instance v1, [COLOR="red"]Lcom/android/incallui/dialpad/DialpadView[/COLOR]$SettingsObserver;

new-instance v2, Landroid/os/Handler;

invoke-direct {v2}, Landroid/os/Handler;-><init>()V

invoke-direct {v1, p0, v2}, [COLOR="red"]Lcom/android/incallui/dialpad/DialpadView[/COLOR]$SettingsObserver;-><init>([COLOR="Red"]Lcom/android/incallui/dialpad/DialpadView[/COLOR];Landroid/os/Handler;)V

invoke-virtual {v1}, [COLOR="red"]Lcom/android/incallui/dialpad/DialpadView[/COLOR]$SettingsObserver;->observe()V
[/COLOR]
return-void
.end method

Important note

:

Wouldn't you know it, the smali I chose to use as an example does not support mcontext so I used getContext here and in the attached DateView$SettingsObserver.smali

After the last .method public constructor method (or with the rest of the access$xxx methods, if they exist) insert this method.

Note the path highlighted in RED must match the smali you are working with.

.method static synthetic access$001([COLOR="Red"]Lcom/android/incallui/dialpad/DialpadView[/COLOR];)Landroid/content/Context;
.locals 1

invoke-virtual {p0}, [COLOR="red"]Lcom/android/incallui/dialpad/DialpadView[/COLOR];->getContext()Landroid/content/Context;

move-result-object v0

return-object v0
.end method

Important note

:

Use this one instead if your smali DOES support mcontext:

.method static synthetic access$001([COLOR="red"]Lcom/android/keyguard/sec/SecKeyguardClockSingleView[/COLOR];)Landroid/content/Context;
.locals 1

iget-object v0, p0, [COLOR="red"]Lcom/android/keyguard/sec/SecKeyguardClockSingleView[/COLOR];->mContext:Landroid/content/Context;

return-object v0
.end method

How to create a new YourFile$SettingsObserver

I don't recommend using

PhoneStatusBar$SettingsObserver.smali or DateView$SettingsObserver.smali

as your templates. The first is specifically for PhoneStatusBar.smali and use DateView$SettingsObserver.smali if your smali does not support mcontext.

Using one of the attached $SettingsObserver files as a template, do the following edits throughout the ENTIRE $SettingsObserver.smali (only highlighting first few lines for brevity).

Find and replace all 14 of the paths to correspond with the smali you are working in.

The .source line is the smali name only. Change this to match the smali you are working in also.

The completed SettingsObserver.smali gets placed in the same folder as the parent smali we are working with.

.class public [COLOR="Red"]Lcom/android/incallui/dialpad/DialpadView[/COLOR]$SettingsObserver;
.super Landroid/database/ContentObserver;
.source "[COLOR="red"]DialpadView[/COLOR].java"

SettingsObserver example files have been attached to this post.

** some MM guide discussions begin here: http://xdaforums.com/showpost.php?p=66480317&postcount=70