Related
I'm trying to get rid of the headset icon in my notification bar and I can't find the .smali and entry I need to edit on the forums or Google. I have no idea how to go about finding it and I don't want to just start messing around in the services.jar. Does anyone know it off hand and can point me where to go? Thanks.
If anyone doesn't know the specific thing needing editing, can you point me in the direction I need to go to figure out what I need?
brandontowey said:
If anyone doesn't know the specific thing needing editing, can you point me in the direction I need to go to figure out what I need?
Click to expand...
Click to collapse
Open framework-res.apk and find drawable with this icon. Then search for it in XMLs or smali files.
Brut.all said:
Open framework-res.apk and find drawable with this icon. Then search for it in XMLs or smali files.
Click to expand...
Click to collapse
Sweet. Thanks.
I'm pretty sure I found the entry in StatusBarPolicy.smali:
.line 848
iget-object v6, p0, Lcom/android/server/status/ StatusBarPolicy;mHeadsetIcon:Lcom/android/server/status/IconData;
const v7, 0x1080363
iput v7, v6, Lcom/android/server/status/IconData;->iconId:I
goto :goto_43
Click to expand...
Click to collapse
I'm not sure how to edit it to get the icon to be hidden. I checked out the how-to on the GPS, Battery, Clock and Alarm and there's not discernible pattern to the different edits. Can anyone help a brotha out?
bump. I don't know computer code, no idea how to go about figuring this out.
Above lines are just to initialize some variables. Find where Lcom/android/server/status/IconData;->iconId:I is used.
Brut.all said:
Above lines are just to initialize some variables. Find where Lcom/android/server/status/IconData;->iconId:I is used.
Click to expand...
Click to collapse
In HTCCdmaStatusBar.smali, there are 4 instances of that:
Code:
.line 342
:pswitch_4
iget-object v0, p0, Lcom/android/server/status/HtcCdmaStatusBar;->mMtGpsIconData:Lcom/android/server/status/IconData;
const v1, 0x20205e2
iput v1, v0, Lcom/android/server/status/IconData;->iconId:I
goto :goto_3
Code:
.line 348
:pswitch_c
iget-object v0, p0, Lcom/android/server/status/HtcCdmaStatusBar;->mMtGpsIconData:Lcom/android/server/status/IconData;
const v1, 0x20205dc
iput v1, v0, Lcom/android/server/status/IconData;->iconId:I
goto :goto_3
Code:
.line 355
:pswitch_14
iget-object v0, p0, Lcom/android/server/status/HtcCdmaStatusBar;->mMtGpsIconData:Lcom/android/server/status/IconData;
const v1, 0x20205de
iput v1, v0, Lcom/android/server/status/IconData;->iconId:I
goto :goto_3
Code:
.line 362
:pswitch_1c
iget-object v0, p0, Lcom/android/server/status/HtcCdmaStatusBar;->mMtGpsIconData:Lcom/android/server/status/IconData;
const v1, 0x20205e0
iput v1, v0, Lcom/android/server/status/IconData;->iconId:I
Am I getting warmer?
bump. I'd love some help with this, I don't think I have it in me to learn how to write whatever code this is so I can figure out how to edit these. Thanks.
Can't copy the link from the xda app but search for (How-To) Remove GPS Reticle on XDA and the read will come up. JsChiSurf posted the needed edit on the second page. Props to him.
Sent from my Evo, who commented on what a purty mouth you have, uh-huh.
Since there is somewhat of a lack of how to's in these forums, I decided to post one for this mod. Linked to me by mysteryemotionz, the thread i pulled it from is here:
http://forum.xda-developers.com/showthread.php?t=946647
I winmerged the edited files and replicated it on the Epic. I'm going to assume you have somewhat of an idea of what you are doing, so please read up and search if you have noob questions, the answers are out there. Other than that I'm happy to help.
This was written for DK28 but the same steps work on EB13.
Flashable zip.
Must have java runtime environment installed and have smali.jar and baksmali.jar.
1.) Pull classes.dex out of /system/framework/services.jar with 7zip
2.) Decompile classes.dex (java -jar baksmali.jar -o classout/ classes.dex)
3.) Edit C:\smali\classout\com\android\server\status\StatusBarIcon.smali with Notepad++
4.) Make the following changes and save the file:
At line 48 change:
Code:
.line 51
iget v6, p2, Lcom/android/server/status/IconData;->type:I
packed-switch v6, :pswitch_data_9a
TO:
Code:
.line 51
iget v6, p2, Lcom/android/server/status/IconData;->type:I
packed-switch v6, :pswitch_data_9c
---------------------------------
At line 93 change:
Code:
.line 63
const/4 v6, 0x6
invoke-virtual {v4, v6, v8, v8, v8}, Landroid/widget/TextView;->setPadding(IIII)V
.line 64
invoke-virtual {v4, v2}, Landroid/widget/TextView;->setLayoutParams(Landroid/view/ViewGroup$LayoutParams;)V
.line 65
iget-object v6, p2, Lcom/android/server/status/IconData;->text:Ljava/lang/CharSequence;
invoke-virtual {v4, v6}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
.line 66
iput-object v4, p0, Lcom/android/server/status/StatusBarIcon;->view:Landroid/view/View;
goto :goto_10
.line 72
.end local v2 #layoutParams:Landroid/widget/LinearLayout$LayoutParams;
.end local v4 #t:Landroid/widget/TextView;
:pswitch_3f
const-string v6, "layout_inflater"
invoke-virtual {p1, v6}, Landroid/content/Context;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
move-result-object v1
check-cast v1, Landroid/view/LayoutInflater;
TO:
Code:
.line 63
const/4 v6, 0x6
const/16 v7, -0x26
invoke-virtual {v4, v6, v8, v7, v8}, Landroid/widget/TextView;->setPadding(IIII)V
.line 64
invoke-virtual {v4, v2}, Landroid/widget/TextView;->setLayoutParams(Landroid/view/ViewGroup$LayoutParams;)V
.line 65
iget-object v6, p2, Lcom/android/server/status/IconData;->text:Ljava/lang/CharSequence;
invoke-virtual {v4, v6}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
.line 66
iput-object v4, p0, Lcom/android/server/status/StatusBarIcon;->view:Landroid/view/View;
goto :goto_10
.line 72
.end local v2 #layoutParams:Landroid/widget/LinearLayout$LayoutParams;
.end local v4 #t:Landroid/widget/TextView;
:pswitch_41
const-string v6, "layout_inflater"
invoke-virtual {p1, v6}, Landroid/content/Context;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
move-result-object v1
check-cast v1, Landroid/view/LayoutInflater;
-----------------------------------
At line 175 change:
Code:
.line 86
iget v6, p2, Lcom/android/server/status/IconData;->number:I
if-lez v6, :cond_93
TO:
Code:
.line 86
iget v6, p2, Lcom/android/server/status/IconData;->number:I
if-lez v6, :cond_95
------------------------------------
At line 208 change:
Code:
.line 90
:cond_93
const/16 v6, 0x8
invoke-virtual {v3, v6}, Landroid/widget/TextView;->setVisibility(I)V
goto/16 :goto_10
.line 51
:pswitch_data_9a
.packed-switch 0x1
:pswitch_11
:pswitch_3f
.end packed-switch
.end method
.method static getIcon(Landroid/content/Context;Lcom/android/server/status/IconData;)Landroid/graphics/drawable/Drawable;
.registers 9
.parameter "context"
.parameter "data"
.prologue
const/4 v5, 0x0
const-string v6, "StatusBar"
TO:
Code:
.line 90
:cond_95
const/16 v6, 0x8
invoke-virtual {v3, v6}, Landroid/widget/TextView;->setVisibility(I)V
goto/16 :goto_10
.line 51
:pswitch_data_9c
.packed-switch 0x1
:pswitch_11
:pswitch_41
.end packed-switch
.end method
.method static getIcon(Landroid/content/Context;Lcom/android/server/status/IconData;)Landroid/graphics/drawable/Drawable;
.registers 9
.parameter "context"
.parameter "data"
.prologue
const/4 v5, 0x0
const-string v6, "StatusBar"
5.) Recompile to new-classes.dex. (java -Xmx512M -jar smali.jar classout/ -o new-classes.dex)
6.) With 7zip, replace classes.dex with your new-classes.dex in services.jar, but be sure to rename it back to classes.dex.
7.) Place in a flashable zip and flash away.
Oooooo yeaaaaaaaaaaaaa
yeah i just updated OP mentioning the addon section of the theme in my sig has a flashable zip already posted fyi.
I'm glad it worked
Android Creative Syndicate- From spontaneous ingenuity, comes creative brilliance
Ok so just for clarification, do I just need to flash the zip or do I need to do the instructions?
Thanks for this info also
Just what I was looking for! Time to reflash
Thanks everyone!
Nice!
...is it possible to change just the AM/PM size? I've been trying to figure that one out.. I just like the looks of it being smaller like in CM
Edit:
StatusBarIcon.smali is identical in CM and our Framework.. must be someplace else lol such a battle to change a font size.
mysteryemotionz mentioned in framework-res.apk, i think in res/layout there is timepicker.xml and maybe one other xml related to time. i havent checked but it might be in there where the font size is.
amosher13 said:
mysteryemotionz mentioned in framework-res.apk, i think in res/layout there is timepicker.xml and maybe one other xml related to time. i havent checked but it might be in there where the font size is.
Click to expand...
Click to collapse
Unfortintly I was wrong with the xml. Thedub already pointed it ot to me.
Android Creative Syndicate- From spontaneous ingenuity, comes creative brilliance
so for clarification, is it actually possible to change the font size throughout the system?
yogi2010 said:
so for clarification, is it actually possible to change the font size throughout the system?
Click to expand...
Click to collapse
its got to be at least for some items. a lot of it will be in framework-res.apk in res/values/styles i think. a lot of the text parameters are here. others are in res/layout etc.... depends on what you want to change. and i'm only familiar with a very small number of them tbh. but check out dreams theme guides in the themes and apps section if you wanna read up on how to decompile an apk and get into this stuff.
amosher13, does this move the clock over or does it actually remove am & pm?
birgertime said:
amosher13, does this move the clock over or does it actually remove am & pm?
Click to expand...
Click to collapse
It removes the am pm and pushes the clock over
Android Creative Syndicate- From spontaneous ingenuity, comes creative brilliance
Same question
konaman said:
Ok so just for clarification, do I just need to flash the zip or do I need to do the instructions?
Thanks for this info also
Click to expand...
Click to collapse
Just flash it
Android Creative Syndicate- From spontaneous ingenuity, comes creative brilliance
Hi sorry to bump this old thread but I've been experimenting with the code snippets in OP's post.
Code:
.line 63
const/4 v6, 0x6
const/16 v7, -0x26
invoke-virtual {v4, v6, v8, v7, v8}, Landroid/widget/TextView;->setPadding(IIII)V
is the only part that really matters apparently. The rest of the code is just shuffling around some resource names for some reason. As I dont actually own an epic 4g (I did this on a dell streak with a rom based on 2.2.2/FRG83G) I dont know what's going on with the mass renaming.
the code works as is: register v7 is loaded to c in setpadding( a, b, c, d) (i dont know what the final variable is in the actual smali code)
which is
Code:
setPadding(int left, int top, int right, int bottom)
Sets the padding.
hence loading a negative value will push it farther to the right.
At least on my rom 0x1 != 1 pixel. It's closer to 0x1 = ~1.5-2.5 pixels as -0x20 leaves 1 visible pixel of AM but -0x21 cuts off the last time digit by approx 1-2 pixels. For mine i'd need like -0x20.5 but as this is hex that's nonsensical.
A better way would be to find where the AM and PM strings get loaded and to NOP that or to change it to a blank/null string, but I have no idea where that is.
TheManii said:
Hi sorry to bump this old thread but I've been experimenting with the code snippets in OP's post.
Code:
.line 63
const/4 v6, 0x6
const/16 v7, -0x26
invoke-virtual {v4, v6, v8, v7, v8}, Landroid/widget/TextView;->setPadding(IIII)V
is the only part that really matters apparently. The rest of the code is just shuffling around some resource names for some reason. As I dont actually own an epic 4g (I did this on a dell streak with a rom based on 2.2.2/FRG83G) I dont know what's going on with the mass renaming.
the code works as is: register v7 is loaded to c in setpadding( a, b, c, d) (i dont know what the final variable is in the actual smali code)
Click to expand...
Click to collapse
+1 -- It would seem TheManii is quite correct with the code snippet he posted above.
It does represent the only change which is necessary to move the clock over to hide the AM/PM.
@amosher13
It appears when you used WinMerge to get a diff between the files you received a handful insignifigant deviations in the resource names probably caused by the difference in source device of the files.
Thank you both for your efforts!
TheManii said:
Code:
setPadding(int left, int top, int right, int bottom)
Sets the padding.
hence loading a negative value will push it farther to the right.
At least on my rom 0x1 != 1 pixel. It's closer to 0x1 = ~1.5-2.5 pixels as -0x20 leaves 1 visible pixel of AM but -0x21 cuts off the last time digit by approx 1-2 pixels. For mine i'd need like -0x20.5 but as this is hex that's nonsensical.
A better way would be to find where the AM and PM strings get loaded and to NOP that or to change it to a blank/null string, but I have no idea where that is.
Click to expand...
Click to collapse
@TheManii
Based on the related XML, it certainly looks like the values here are in the dp unit, so, for the screen size of our devices, the values would indeed be multiplied by about 1.5.
Also, I'm fairly certain the time gets loaded with the AM/PM attached, as with the dateformat class, which would require additional formatting to get rid of it.
I have sort of thought about possibly using the simpledateformat class to change the am/pm to a/p, but now I moved my clock next to the date in the pulldown.
Check this out
How funny is this?...I'm looking around XDA for info on date formatting, and I stumble across this post JsChiSurf over in the EVO 4G forums.
http://forum.xda-developers.com/showpost.php?p=11753928&postcount=187
It's so simple...I'm far to new to this smali stuff, so I had no idea this method of manipulating the string would work.
Anyhow, I manually merge the appropriate changes into our StatusBarPolicy.smali, then created a diff for ya'll to see the changes.
Code:
--- StatusBarPolicy.smali.orig 2011-08-14 15:19:35.000000000 -0500
+++ StatusBarPolicy.smali 2011-08-14 15:29:04.000000000 -0500
@@ -4919,7 +4919,7 @@
.end method
.method private final updateClock()V
- .registers 5
+ .locals 6
.prologue
.line 889
@@ -4948,6 +4948,22 @@
invoke-virtual {v1, v2}, Ljava/text/DateFormat;->format(Ljava/util/Date;)Ljava/lang/String;
+ move-result-object v1
+
+ const-string v4, " PM"
+
+ const-string v5, ""
+
+ invoke-virtual {v1, v4, v5}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
+
+ move-result-object v1
+
+ const-string v4, " AM"
+
+ const-string v5, ""
+
+ invoke-virtual {v1, v4, v5}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
+
move-result-object v1
iput-object v1, v0, Lcom/android/server/status/IconData;->text:Ljava/lang/CharSequence;
This is certainly the most direct way to do it by totally removing the am/pm indicator....Thanks, JsChiSurf!!!
Code diff seems to work perfectly, i'll do a code analysis in psuedocode soon and explain what the code does, but basically it does (one of the two ways) what i expected needed to get done;
Basically it:
get formatted date from java/text/dateformat and shove it into string1
shove it into a tempory string2
make temporary string2 with " AM" and temporary string 3 with ""
calls the replacecharsequence(string1, string2, string3)
which does "for every time it sees string2 inside string one, replace it with string3"
and does the entire thing again for PM
it seems to work perfectly with 12/24h clock just like on GB, no messy moving the entire statusbar rightwards
Hi again lads/gents,
Today i want to share to you how to enable 2G/3G Toggle feature that was commonly found on CyanogenMod and/or AOKP into your custom Android ROM. My code is based from Xperia Ray but shouldn't be too different between different phone version, because the concept in essence is to bring up the default toggle hidden in Settings menu to be switchable with external app or button.
The common problem when we try to implement this kind of mod is that Android system prevents system changes from outside system's apk, and added to the fact that the only apk allowed for Network Mode changes is the one with uid set as "phone" at its AndroidManifest.xml. When you thought it's a part of Settings.apk, actually Settings.apk only calls for Phone.apk Settings page.
So to do a workaround for that, you need to alter the phone.apk itself to be able to receive custom Broadcast from external apk and then switch the mode when required.
This is what you need:
1. Rooted phone
2. Phone.apk (or in my case SemcPhone.apk)
3. Basic Knowledge of Android Broadcast and Receiver concept
4. Custom toggle app/Status Bar Widget (in my case, i'll use lidroid's Power Button on Status Bar as a toggle utility)
5. Any APK Manager, preferably one that can be set to not decode resource file.
The steps are:
1. Place the Receiver files inside Phone.apk
2. Register the Receiver at runtime through Phone Application smali file
3. Compile Phone.apk
4. Implement Toggle mechanism for 2G/3G on Toggling app
1. Place the Receiver files inside Phone.apk
This is used as a Receiver of Broadcast Message from User App to start Toggling the Network Mode. There are 3 files you need to put on decompiled Phone.apk:
smali\com\android\phone\NetworkModeReceiver.smali -> The Main Code
Code:
.class public Lcom/android/phone/NetworkModeReceiver;
.super Landroid/content/BroadcastReceiver;
.source "NetworkModeReceiver.java"
# annotations
.annotation system Ldalvik/annotation/MemberClasses;
value = {
Lcom/android/phone/NetworkModeReceiver$1;,
Lcom/android/phone/NetworkModeReceiver$MyHandler;
}
.end annotation
# static fields
.field private static final TAG:Ljava/lang/String; = "NetworkModeReceiver"
# instance fields
.field private mHandler:Lcom/android/phone/NetworkModeReceiver$MyHandler;
# direct methods
.method public constructor <init>()V
.locals 2
.prologue
.line 31
invoke-direct {p0}, Landroid/content/BroadcastReceiver;-><init>()V
new-instance v0, Lcom/android/phone/NetworkModeReceiver$MyHandler;
const/4 v1, 0x0
invoke-direct {v0, p0, v1}, Lcom/android/phone/NetworkModeReceiver$MyHandler;-><init>(Lcom/android/phone/NetworkModeReceiver;Lcom/android/phone/NetworkModeReceiver$1;)V
iput-object v0, p0, Lcom/android/phone/NetworkModeReceiver;->mHandler:Lcom/android/phone/NetworkModeReceiver$MyHandler;
return-void
.end method
# virtual methods
.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V
.locals 5
.parameter "context"
.parameter "intent"
const-string v0, "com.android.phone.CHANGE_NETWORK_MODE"
.line 41
invoke-virtual {p2}, Landroid/content/Intent;->getAction()Ljava/lang/String;
move-result-object v1
invoke-virtual {v1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v1
if-eqz v1, :cond_0
.line 43
const-string v0, "com.android.phone.NEW_NETWORK_MODE"
const v1, 0x0
invoke-virtual {p2, v0, v1}, Landroid/content/Intent;->getIntExtra(Ljava/lang/String;I)I
move-result v1
.line 44
new-instance v0, Ljava/lang/StringBuilder;
invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V
const-string v3, "Receive Network Mode "
invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
sget-object v2, Lcom/android/phone/NetworkModeReceiver;->TAG:Ljava/lang/String;
.line 45
invoke-static {v2, v0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
.line 46
invoke-virtual {p1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v3
const-string v2, "preferred_network_mode"
invoke-static {v3, v2, v1}, Landroid/provider/Settings$Secure;->putInt(Landroid/content/ContentResolver;Ljava/lang/String;I)Z
iget-object v4, p0, Lcom/android/phone/NetworkModeReceiver;->mHandler:Lcom/android/phone/NetworkModeReceiver$MyHandler;
.line 48
const/4 v3, 0x1
invoke-virtual {v4, v3}, Lcom/android/phone/NetworkModeReceiver$MyHandler;->obtainMessage(I)Landroid/os/Message;
move-result-object v4
.line 49
invoke-static {}, Lcom/android/internal/telephony/PhoneFactory;->getDefaultPhone()Lcom/android/internal/telephony/Phone;
move-result-object v3
invoke-interface {v3, v1, v4}, Lcom/android/internal/telephony/Phone;->setPreferredNetworkType(ILandroid/os/Message;)V
:cond_0
return-void
.end method
As you can see, We will use Intent named as "com.android.phone.CHANGE_NETWORK_MODE" with the Extras(or attribute as a layman's term) named as "com.android.phone.NEW_NETWORK_MODE"
smali\com\android\phone\NetworkModeReceiver$1.smali -> Helper Class for MyHandler inner class.
Code:
.class synthetic Lcom/android/phone/NetworkModeReceiver$1;
.super Ljava/lang/Object;
.source "NetworkModeReceiver.java"
# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
value = Lcom/android/phone/NetworkModeReceiver;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x1008
name = null
.end annotation
smali\com\android\phone\NetworkModeReceiver$MyHandler.smali -> Does nothing, only used for Receiving a rollback message from system for UI element - which in this method is not quite usable. But it's there for compatibility reason.
Code:
.class Lcom/android/phone/NetworkModeReceiver$MyHandler;
.super Landroid/os/Handler;
.source "NetworkModeReceiver.java"
# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
value = Lcom/android/phone/NetworkModeReceiver;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x2
name = "MyHandler"
.end annotation
# instance fields
.field final synthetic this$0:Lcom/android/phone/NetworkModeReceiver;
# direct methods
.method private constructor <init>(Lcom/android/phone/NetworkModeReceiver;)V
.locals 0
.parameter
.prologue
.line 628
iput-object p1, p0, Lcom/android/phone/NetworkModeReceiver$MyHandler;->this$0:Lcom/android/phone/NetworkModeReceiver;
invoke-direct {p0}, Landroid/os/Handler;-><init>()V
return-void
.end method
.method synthetic constructor <init>(Lcom/android/phone/NetworkModeReceiver;Lcom/android/phone/NetworkModeReceiver$1;)V
.locals 0
.parameter "x0"
.parameter "x1"
.prologue
.line 628
invoke-direct {p0, p1}, Lcom/android/phone/NetworkModeReceiver$MyHandler;-><init>(Lcom/android/phone/NetworkModeReceiver;)V
return-void
.end method
.method private handleGetPreferredNetworkTypeResponse(Landroid/os/Message;)V
.locals 9
.parameter "msg"
return-void
.end method
.method private handleSetPreferredNetworkTypeResponse(Landroid/os/Message;)V
.locals 2
.parameter "msg"
return-void
.end method
.method private resetNetworkModeToDefault()V
.locals 3
.prologue
return-void
.end method
# virtual methods
.method public handleMessage(Landroid/os/Message;)V
.locals 1
.parameter "msg"
.prologue
.line 635
iget v0, p1, Landroid/os/Message;->what:I
packed-switch v0, :pswitch_data_0
.line 643
:goto_0
return-void
.line 637
:pswitch_0
invoke-direct {p0, p1}, Lcom/android/phone/NetworkModeReceiver$MyHandler;->handleGetPreferredNetworkTypeResponse(Landroid/os/Message;)V
goto :goto_0
.line 640
:pswitch_1
invoke-direct {p0, p1}, Lcom/android/phone/NetworkModeReceiver$MyHandler;->handleSetPreferredNetworkTypeResponse(Landroid/os/Message;)V
goto :goto_0
.line 635
:pswitch_data_0
.packed-switch 0x0
:pswitch_0
:pswitch_1
.end packed-switch
.end method
You need to download from the attachment and put them into smali\com\android\phone folder.
2. Register the Receiver at runtime through Phone Application smali file
Now you have the Receiver installed, you need to initiate and register the Receiver at phone app startup. There are 2 methods available:
Add another line to AndroidManifest.xml -> The simplest one but not practical for system app of stock ROM since the AndroidManifest.xml requires to be signed to be functional.
Alter PhoneApp.smali (it can be named something else->The point is you need Phone's Application main code to be altered) to register the receiver when it's called -> This is the way to go.
This is how you alter the PhoneApp.smali:
Give a space to store the Receiver inside the PhoneApp.smali, named as mModeReceiver (Insert the Bold Line)
Code:
.field mLastPhoneState:Lcom/android/internal/telephony/Phone$State;
.field private final mMediaButtonReceiver:Landroid/content/BroadcastReceiver;
[B].field private final mModeReceiver:Landroid/content/BroadcastReceiver;[/B]
.field private mNationalRoamingSettings:I
.field private mNationalRoamingSupported:Z
Initiate the Receiver Object and store it into the available space (Insert the Bold Line)
Code:
.method public constructor <init>()V
.
.
.line 233
new-instance v0, Lcom/android/phone/PhoneApp$PhoneAppBroadcastReceiver;
const/4 v1, 0x0
invoke-direct {v0, p0, v1}, Lcom/android/phone/PhoneApp$PhoneAppBroadcastReceiver;-><init>(Lcom/android/phone/PhoneApp;Lcom/android/phone/PhoneApp$1;)V
iput-object v0, p0, Lcom/android/phone/PhoneApp;->mReceiver:Landroid/content/BroadcastReceiver;
[B] .line 236
new-instance v0, Lcom/android/phone/NetworkModeReceiver;
invoke-direct {v0}, Lcom/android/phone/NetworkModeReceiver;-><init>()V
iput-object v0, p0, Lcom/android/phone/PhoneApp;->mModeReceiver:Landroid/content/BroadcastReceiver;[/B]
.line 238
new-instance v0, Lcom/android/phone/SemcMediaButtonBroadcastReceiver;
invoke-direct {v0}, Lcom/android/phone/SemcMediaButtonBroadcastReceiver;-><init>()V
iput-object v0, p0, Lcom/android/phone/PhoneApp;->mMediaButtonReceiver:Landroid/content/BroadcastReceiver;
.
.
.end method
Register the Receiver
The following is to register the Receiver when the Phone app is created (onCreate). When registered, It will start listening to the phone activity so later it can receive a toggle message from toggle app. And not just any message that this receiver can read, We limit this Receiver to only hear a filtered Intent with name of "com.android.phone.CHANGE_NETWORK_MODE" as explained above.
Code:
.method public onCreate()V
.
.
.line 630
const-string v1, "com.android.phone.intent.ACTION_DATA_TRAFFIC_SWITCH"
invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V
.line 631
iget-object v1, p0, Lcom/android/phone/PhoneApp;->mReceiver:Landroid/content/BroadcastReceiver;
invoke-virtual {p0, v1, v0}, Lcom/android/phone/PhoneApp;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;
[B] .line 633
new-instance v0, Landroid/content/IntentFilter;
const-string v1, "com.android.phone.CHANGE_NETWORK_MODE"
invoke-direct {v0, v1}, Landroid/content/IntentFilter;-><init>(Ljava/lang/String;)V
iget-object v1, p0, Lcom/android/phone/PhoneApp;->mModeReceiver:Landroid/content/BroadcastReceiver;
invoke-virtual {p0, v1, v0}, Lcom/android/phone/PhoneApp;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;[/B]
.line 638
new-instance v0, Landroid/content/IntentFilter;
const-string v1, "android.intent.action.MEDIA_BUTTON"
invoke-direct {v0, v1}, Landroid/content/IntentFilter;-><init>(Ljava/lang/String;)V
.line 642
const/16 v1, 0x3e0
invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->setPriority(I)V
.line 645
iget-object v1, p0, Lcom/android/phone/PhoneApp;->mMediaButtonReceiver:Landroid/content/BroadcastReceiver;
invoke-virtual {p0, v1, v0}, Lcom/android/phone/PhoneApp;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;
.
.
.end method
3. Compile the Phone.apk
You need to compile the phone app back. As it was with Sony's code, it was clear that i need to decompile ONLY the source, but not the resource part of the apk because when compiled back it will be broken. So try to decompile it at the source only.
4. Implement the Toggle App to send a Broadcast Intent
Now this is the part where you have to determine what mode is supported by your phone. This is the value of Android supported value that will be sent as a Broadcast Intent:
Code:
int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */
int NETWORK_MODE_GSM_ONLY = 1; /* GSM only */
int NETWORK_MODE_WCDMA_ONLY = 2; /* WCDMA only */
int NETWORK_MODE_GSM_UMTS = 3; /* GSM/WCDMA (auto mode, according to PRL) AVAILABLE Application Settings menu*/
int NETWORK_MODE_CDMA = 4; /* CDMA and EvDo (auto mode, according to PRL) AVAILABLE Application Settings menu*/
int NETWORK_MODE_CDMA_NO_EVDO = 5; /* CDMA only */
int NETWORK_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
int NETWORK_MODE_GLOBAL = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL) AVAILABLE Application Settings menu*/
So if your phone only supports WCDMA(3G) as max, you should use value 0,1, and 2 only.
The following is my 2G/3G simple toggle mode from Lidroid's Status Bar Widget code. You should adapt the code yourself if you're using something else. But as a guide, this is the logic:
create a new Intent with name "com.android.phone.CHANGE_NETWORK_MODE"
take current mode
Apply the next value into the newly created Intent as Extra named "com.android.phone.NEW_NETWORK_MODE"
Broadcast the Intent to the System (which will be read by Phone.apk).
The logic above can be observed in the method toggleState() on the following code:
Code:
.class public Lcom/lidroid/systemui/quickpanel/NetworkModeButton;
.super Lcom/lidroid/systemui/quickpanel/PowerButton;
.source "NetworkModeButton.java"
# static fields
.field private static final CM_MODE_3GSM_ONLY:I = 0x1
.field private static final CM_MODE_3G_ONLY:I = 0x0
.field private static final CM_MODE_3G_PREFERRED:I = 0x2
.field private static final OBSERVED_URIS:Ljava/util/List; = null
.annotation system Ldalvik/annotation/Signature;
value = {
"Ljava/util/List",
"<",
"Landroid/net/Uri;",
">;"
}
.end annotation
.end field
.field private static final TAG:Ljava/lang/String; = "NetworkModeButton"
# direct methods
.method static constructor <clinit>()V
.locals 3
.prologue
const/16 v2, 0x0
.line 21
new-instance v0, Ljava/util/ArrayList;
invoke-direct {v0}, Ljava/util/ArrayList;-><init>()V
sput-object v0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->OBSERVED_URIS:Ljava/util/List;
.line 23
sget-object v0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->OBSERVED_URIS:Ljava/util/List;
const-string v1, "preferred_network_mode"
invoke-static {v1}, Landroid/provider/Settings$Secure;->getUriFor(Ljava/lang/String;)Landroid/net/Uri;
move-result-object v1
invoke-interface {v0, v1}, Ljava/util/List;->add(Ljava/lang/Object;)Z
return-void
.end method
.method public constructor <init>()V
.locals 2
.prologue
.line 43
invoke-direct {p0}, Lcom/lidroid/systemui/quickpanel/PowerButton;-><init>()V
const-string v0, "toggleNetworkMode"
iput-object v0, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mType:Ljava/lang/String;
return-void
.end method
.method private static getCurrentNetworkMode(Landroid/content/Context;)I
.locals 3
.parameter "context"
.prologue
.line 167
const/16 v0, 0x0
.line 169
.local v0, state:I
:try_start_0
invoke-virtual {p0}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v1
const-string v2, "preferred_network_mode"
invoke-static {v1, v2}, Landroid/provider/Settings$Secure;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;)I
:try_end_0
.catch Landroid/provider/Settings$SettingNotFoundException; {:try_start_0 .. :try_end_0} :catch_0
move-result v0
.line 173
:goto_0
return v0
.line 171
:catch_0
move-exception v1
goto :goto_0
.end method
# virtual methods
.method protected getObservedUris()Ljava/util/List;
.locals 1
.annotation system Ldalvik/annotation/Signature;
value = {
"()",
"Ljava/util/List",
"<",
"Landroid/net/Uri;",
">;"
}
.end annotation
.prologue
.line 163
sget-object v0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->OBSERVED_URIS:Ljava/util/List;
return-object v0
.end method
.method protected getText()I
.locals 1
.prologue
.line 93
const v0, 0x7f08007d
return v0
.end method
.method protected handleLongClick()Z
.locals 3
.prologue
.line 126
new-instance v0, Landroid/content/Intent;
const-string v1, "android.intent.action.MAIN"
invoke-direct {v0, v1}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
.line 127
.local v0, intent:Landroid/content/Intent;
const-string v1, "com.android.phone"
const-string v2, "com.android.phone.Settings"
invoke-virtual {v0, v1, v2}, Landroid/content/Intent;->setClassName(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
.line 128
const/high16 v1, 0x1000
invoke-virtual {v0, v1}, Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;
.line 129
iget-object v1, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mView:Landroid/view/View;
invoke-virtual {v1}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v1
invoke-virtual {v1, v0}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
.line 130
const/4 v1, 0x1
return v1
.end method
[B].method protected toggleState()V
.locals 5
.prologue
const/4 v4, 0x2
const/4 v1, 0x1
const-string v2, "com.android.phone.CHANGE_NETWORK_MODE"
.line 83
iget-object v3, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mView:Landroid/view/View;
invoke-virtual {v3}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v3
.line 84
.local v3, context:Landroid/content/Context;
invoke-static {v3}, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->getCurrentNetworkMode(Landroid/content/Context;)I
move-result v0
.line 85
add-int v0, v0, v1
if-le v0, v4, :cond_0
const/4 v0, 0x0
.line 86
:cond_0
new-instance v4, Landroid/content/Intent;
invoke-direct {v4, v2}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
const-string v2, "com.android.phone.NEW_NETWORK_MODE"
invoke-virtual {v4, v2, v0}, Landroid/content/Intent;->putExtra(Ljava/lang/String;I)Landroid/content/Intent;
invoke-virtual {v3, v4}, Landroid/content/Context;->sendBroadcast(Landroid/content/Intent;)V
return-void
.end method[/B]
.method protected updateState()V
.locals 3
.line 90
iget-object v1, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mView:Landroid/view/View;
invoke-virtual {v1}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v1
invoke-static {v1}, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->getCurrentNetworkMode(Landroid/content/Context;)I
move-result v0
.line 92
const v1, 0x0
if-ne v0, v1, :cond_0
const v2, 0x7f0200d4
iput v2, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mIcon:I
const/4 v2, 0x1
iput v2, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mState:I
.line 93
:goto_0
return-void
.line 94
:cond_0
const v1, 0x1
if-ne v0, v1, :cond_1
const v2, 0x7f0200d3
iput v2, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mIcon:I
const/4 v2, 0x2
iput v2, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mState:I
goto :goto_0
.line 96
:cond_1
const v2, 0x7f0200d5
iput v2, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mIcon:I
const/4 v2, 0x1
iput v2, p0, Lcom/lidroid/systemui/quickpanel/NetworkModeButton;->mState:I
goto :goto_0
.end method
Or you could download from attachment if you happen to use Lidroid's code too.
Compile back your apk and voila!
Hope this tutorial helps Any question, please reply and i'll help as best as i can.
im using galaxy note. succed???
dedisuhermanto said:
im using galaxy note. succed???
Click to expand...
Click to collapse
try it first gan.
First - Thank you, very good job
Second, i would like to add new receiver in Androidmanifest.xml
so is that correct
Code:
<receiver android:name="NetworkModeReceiver">
<intent-filter>
<action android:name="com.android.phone.CHANGE_NETWORK_MODE" />
<action android:name="com.android.phone.NEW_NETWORK_MODE" />
</intent-filter>
</receiver>
is it enough?
-------------------------------------------
Yes found it enoughs
zcop said:
First - Thank you, very good job
Second, i would like to add new receiver in Androidmanifest.xml
so is that correct
Code:
<receiver android:name="NetworkModeReceiver">
<intent-filter>
<action android:name="com.android.phone.CHANGE_NETWORK_MODE" />
<action android:name="com.android.phone.NEW_NETWORK_MODE" />
</intent-filter>
</receiver>
is it enough?
-------------------------------------------
Yes found it enoughs
Click to expand...
Click to collapse
Well if you can sign it at AndroidManifest level, yes you don't have to edit the smali.
Does it work with another devices whose get the world phone capabilities ?
Thanks
This's useful thread. Can we use 3G only mode using this method?
zozor said:
Does it work with another devices whose get the world phone capabilities ?
Thanks
Click to expand...
Click to collapse
Yes it will, you just have to know what's the integer number that represents the code of the network that is available to be used. IIRC you can look for it on the Phone.apk/res/values/arrays.xml
android addicts said:
This's useful thread. Can we use 3G only mode using this method?
Click to expand...
Click to collapse
Yes, it was designed to switch from 3G-3G/2G-2G (0-1-2) If you like to change the sequence, you need to look at the updateState method above and change the basic sequencing act with additional conditional if.
hansip87 said:
Yes it will, you just have to know what's the integer number that represents the code of the network that is available to be used. IIRC you can look for it on the Phone.apk/res/values/arrays.xml
Click to expand...
Click to collapse
I looked out the values on the Phone.apk/res/values/arrays.xml it's really different ,that's may cause the first one come from the stock sense 3.6 and another for a port of sense 4.
My goal is to mod the sense phone.apk to get world capabilities enable .
Other one tell me that if the phone.apk is mod I should also mod the framework.telephony ,isnt it? But at this stage I am a kind of confuse.
Back to my question ,in the arrays.xml ,some string name are apktool,is it a bug ?
In the Sense 4, the arrays invoke use this form @com.htc:string/st_automatic,while the sense 3.6 xml invoke a string. Is it where the issue is located ?
I also notice that the public.xml (completely ) and the string.xml are different .
Thanks enough for your help with the xml , I can have a big idea now of want the smali does ...
zozor said:
I looked out the values on the Phone.apk/res/values/arrays.xml it's really different ,that's may cause the first one come from the stock sense 3.6 and another for a port of sense 4.
My goal is to mod the sense phone.apk to get world capabilities enable .
Other one tell me that if the phone.apk is mod I should also mod the framework.telephony ,isnt it? But at this stage I am a kind of confuse.
Back to my question ,in the arrays.xml ,some string name are apktool,is it a bug ?
In the Sense 4, the arrays invoke use this form @com.htc:string/st_automatic,while the sense 3.6 xml invoke a string. Is it where the issue is located ?
I also notice that the public.xml (completely ) and the string.xml are different .
Thanks enough for your help with the xml , I can have a big idea now of want the smali does ...
Click to expand...
Click to collapse
Well, actually the apk will decide based on phone's hardware configuration, so this mod is not a smart one unfortunately (aka, only playing statically between 0-1-2 regardless on what configuration), so you have to research further to find out how the phone takes the correct array. but since it is per phone mod so i haven't research it further to enable such technique.
In my Phone app, the used array values inside /res/values/array.xml are the following:
Code:
<string-array name="clh_preferred_network_mode_values"> // this is the real value for each radio box inside Network Mode checkboxes inside Settings.
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
.
.
.
<string-array name="clh_preferred_network_mode_choices"> //This one is used for Settings app display name for each gsm network.
<item>WCDMA only</item>
<item>GSM only</item>
<item>WCDMA (preferred)/GSM</item>
</string-array>
Those arrays correspond to my setting like this:
That is the value shown when i select the mode through Android setting menu, so if you can find the array containing the same label with the one on your Settings menu, just take the value that corresponds to that label (e.g. the above sample tells me that no 2 corresponds to WCDMA only, 1 to GSM only, and so on), and then thru NetworkModeButton.smali, you just have to change the logic from normal sequence (0-1-2-0-1-2-....) like i did to anything that fits your need.
This is a portion part of the array code
Code:
<string-array name="clir_display_values">
<item>Network default</item>
<item>Hide number</item>
<item>Show number</item>
</string-array>
<string-array name="clir_values">
<item>DEFAULT</item>
<item>HIDE</item>
<item>SHOW</item>
</string-array>
<string-array name="preferred_network_mode_choices">
<item>Global</item>
<item>EvDo only</item>
<item>CDMA w/o EvDo</item>
<item>CDMA / EvDo auto</item>
<item>GSM / WCDMA auto</item>
<item>WCDMA only</item>
<item>GSM only</item>
<item>GSM / WCDMA preferred</item>
</string-array>
<string-array name="preferred_network_mode_values">
<item>7</item>
<item>6</item>
<item>5</item>
<item>4</item>
<item>3</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
But it doesn't seems to work when I am on CDMA mode . Can load this setting or the same picture as you .
And the sim-card can't be read.
I have attache the two arrays Sense4 & sense 3.6 with the word phone capacities enable,if you can help me to sort out this issue.
zozor said:
This is a portion part of the array code
Code:
<string-array name="clir_display_values">
<item>Network default</item>
<item>Hide number</item>
<item>Show number</item>
</string-array>
<string-array name="clir_values">
<item>DEFAULT</item>
<item>HIDE</item>
<item>SHOW</item>
</string-array>
<string-array name="preferred_network_mode_choices">
<item>Global</item>
<item>EvDo only</item>
<item>CDMA w/o EvDo</item>
<item>CDMA / EvDo auto</item>
<item>GSM / WCDMA auto</item>
<item>WCDMA only</item>
<item>GSM only</item>
<item>GSM / WCDMA preferred</item>
</string-array>
<string-array name="preferred_network_mode_values">
<item>7</item>
<item>6</item>
<item>5</item>
<item>4</item>
<item>3</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
But it doesn't seems to work when I am on CDMA mode . Can load this setting or the same picture as you .
And the sim-card can't be read.
I have attache the two arrays Sense4 & sense 3.6 with the word phone capacities enable,if you can help me to sort out this issue.
Click to expand...
Click to collapse
Umm, are you sure you have all those 8 choices on Settings menu?
I don't have it , lol .
When I am on cdma , I have any of them. The option is unavailable
zozor said:
I don't have it , lol .
When I am on cdma , I have any of them. The option is unavailable
Click to expand...
Click to collapse
well the rule is just to match the value with the Settings available choices. don't know anything else there is.
Thanks bro,
I will whatever possible with this knowlegde .
Force closing phone.apk
@hansip87
Hi, Thanks alot for posting this tutorial. I have been trying this mod on the samsung galaxy beam (gt-i8530), but have not had any luck. I get a force close of the phone.apk upon booting into the system. My phone runs the stock touchwiz4 interface, and i have successfully deodexed the system and implemented the 14 toggle mod by lidroid. The error i get in my logcat is as follows:
W/dalvikvm( 1949): VFY: rejecting opcode 0x59 at 0x000f
W/dalvikvm( 1949): VFY: rejected Lcom/android/phone/PhoneApp;.<init> ()V
W/dalvikvm( 1949): Verifier rejected class Lcom/android/phone/PhoneApp;
W/dalvikvm( 1949): Class init failed in newInstance call (Lcom/android/phone/PhoneApp
W/dalvikvm( 1949): threadid=1: thread exiting with uncaught exception (group=0x4001e578)
E/AndroidRuntime( 1949): FATAL EXCEPTION: main
E/AndroidRuntime( 1949): java.lang.VerifyError: com.android.phone.PhoneApp
Can you please point me in the right direction?
I get no faults from the systemui.apk, but no options appear in the quickpanelsettings.apk for the network mode, so do I have to modify the quickpanelsettings.apk that comes with the lidroid mod?
Ooh I ll try to put a 2g/3g toggle into sammy toggles.
Thanks for the explaination, hope to get it
Ok.but now I need the icons for the toggle in statusbar right? How many? 3 right? I've WCDMA GSM GSM-WCDMA. So I need 3 icons. Names of the icons?
mewzik86 said:
@hansip87
Hi, Thanks alot for posting this tutorial. I have been trying this mod on the samsung galaxy beam (gt-i8530), but have not had any luck. I get a force close of the phone.apk upon booting into the system. My phone runs the stock touchwiz4 interface, and i have successfully deodexed the system and implemented the 14 toggle mod by lidroid. The error i get in my logcat is as follows:
W/dalvikvm( 1949): VFY: rejecting opcode 0x59 at 0x000f
W/dalvikvm( 1949): VFY: rejected Lcom/android/phone/PhoneApp;.<init> ()V
W/dalvikvm( 1949): Verifier rejected class Lcom/android/phone/PhoneApp;
W/dalvikvm( 1949): Class init failed in newInstance call (Lcom/android/phone/PhoneApp
W/dalvikvm( 1949): threadid=1: thread exiting with uncaught exception (group=0x4001e578)
E/AndroidRuntime( 1949): FATAL EXCEPTION: main
E/AndroidRuntime( 1949): java.lang.VerifyError: com.android.phone.PhoneApp
Can you please point me in the right direction?
I get no faults from the systemui.apk, but no options appear in the quickpanelsettings.apk for the network mode, so do I have to modify the quickpanelsettings.apk that comes with the lidroid mod?
Click to expand...
Click to collapse
The error might be caused by the incorrect placed code on the PhoneApp.smali. Maybe the incorrect named class inside there.
To make it able to be displayed on QuickPanelSettings.apk, yes you need to add a line or two there. I forgot which smali, but you'll find it fast by searching for other button's registration (read:written) code on the smalis.
Using Manual Intents
Hi,
I modified the Phone.apk for my RAZR xt910, and since it has not crashed or anything, i take that i did everything right.
But i dont wish to use the status bar toggle, instead i want to trigger it through broadcast intent through apps like LLama or Manual intent shortcuts.
Will it work for the intents? and if yes then can you tell me how i should write the intents. I am new to all of this so didnt know how to check it using the intents.
Thanks in advance
Hello xda'ers,
after loads of PM, requests, and lot of people I found googlin complainting about this "feature" I give to you the fix.
There are 2 ways to disable edge zoom, but I give you the easiest one.
Requirements:
smali/baksmali (and its use) or apktool (and its use)
Decompile framework.jar
go to:
smali\android\webkit\ZoomManager.smali
look for:
.method setEdgeZoom(Z)V
delete the red line and add the green line
Code:
.method setEdgeZoom(Z)V
.registers 12
.parameter "enabled"
.prologue
[COLOR="Red"]const/4 v5, 0x1[/COLOR]
[COLOR="SeaGreen"]const/4 v5, 0x0[/COLOR]
const/4 v4, 0x0
.line 1602
invoke-virtual {p0}, Landroid/webkit/ZoomManager;->getScaleGestureDetector()Landroid/view/ScaleGestureDetector;
move-result-object v6
if-eqz v6, :cond_41
...
Recompile and enjoy.
If this made your day, consider to hit thank button.
Cheers
How does this Edge Zoom feature work?
Mirko, are you talking about some earlier firmwares, because this feature is not
present on dll5 or dll7?
Actually i'd like to know how to get this feature back! It was really useful but it was removed from the newest firmware.
Sent from my GT-N7100 using Xparent ICS Tapatalk 2
I am trying to enable this as well but .method setEdgeZoom is nowhere to be found in ZoomManager.smali. I am on N7105 DLL4 rom. What was your other way to enable/disable this feature? TIA!
I posted this in S2 section a while ago but after talking with a senior mod I'm posting here as its useful on this device
Firstly I am by no means an expert and am just trying to share what i have learnt about smali as its hard to find much info about general smali. Contributions to the thread are always welcome
For the last year or so I have been developing AllianceROM on the i9100. During this time I have learnt lots about smali through a combination of trial and error and guides I have found here on XDA. The guides are great but one thing that stands out is that they all follow the same pattern of “Find a certain line in a certain file and copy/paste" to replace methods or chunks of code for the desired outcome. Whilst this is a great means to an end it is only a means to that particular end. Most people wont actually understand what they are doing or how it works and will blindly do as instructed.
So I thought that I would try to write some general guides. The aim is to give you the means to dream up your own mods and know how to go about implementing them from scratch by yourself. As I say, I am by no means an expert but hopefully there should be enough here to set you on your way. These are the methods I used to create many of the mods in alliance, lots of which didn’t exist on Touchwiz devices before.
You will need certain tools to do this but I am not going into how to decompile etc. Before attempting this you should have a good knowledge of decompiling apks and modding in general and have the following tools available:
ADB
Notepad ++
A good image editor like Photoshop or GIMP
The guides are in 3 sections:
Coloring stuff with color pickers
Toggling stuff to show or hide
List choices for things like toggles in view etc
For the purposes of these guides I am using an apk from our legendary alliance developer ficeto. He has made this app to enable us to easily add color pickers, checkboxes and lists by adding a single line to an xml. Huge huge thanks to him as he made this a lot easier!! You can use this to test your mods but please dont rename everything from ficeto to "ubermodders" or something and try to pass it off as your own. If you do it will be reported It is to be used as is, not changed or renamed (this causes problems for people installing alliamceMOD) and dont forget to credit ficeto!!
Please feel free to ask general smali questions here too!
So lets get started!!
Coloring Stuff:
Text Colors
There is a ton of stuff in alliance that can be colored, from text to images or backgrounds. Text works by using the setTextColor method and images and backgrounds use setColorFilter to lay a color over the top of an image ot setBackgroundColor to fill the entire background. I will cover one of each in this section starting with text color. The 3 methods use similar code and text color is the easiest to start with.
So….you decide you want to change the color of some text using a picker. For this example I will use the dropdown date. Where do you start? As you probably know dropdown stuff is dealt with by SystemUI.apk. When you decompile that you are faced with a ton of smali files. The best way to start is to use a handy function in Notepad++ called “Find in Files” which will search for certain text within files. Funnily enough its under the Search menu at the top!!
In this case the first port of call would be to search for the obvious word “date”. This returns a ton of results and you should see an obvious file called DateView.smali. If your search doesn’t return much for your specific choice of text then you have a couple of options:
1) look in the layout xml and find the id for the view you want to change. Look the id up in public.xml and then search that using “Find in Files” again. If you are unsure of the text view id then use hierarchy viewer from the tools folder of the sdk which will show you all the views on your screen
2) look through the smali files manually for anything that sounds like it might contain your target
So you think you found the right smali. Open it and search for “setText(Ljava/lang/CharSequenceV”. This will hopefully return a line something like this:
invoke-virtual {p0, v5}, Lcom/android/systemui/statusbar/policy/DateView;->setText(Ljava/lang/CharSequenceV
Scroll up until you see the name of the method. This should give you a good idea if you have the right text. In this case that line was in .method private final updateClock()V which sounds about right!
What this line is doing is calling settext with the parameter Ljava/lang/CharSequence which is the date string. Invoke virtual calls the method and the bit in the brackets {p0, v5} is the date view (p0 means “this file”) and the string (v5). The v is a register. Registers are used to store things. A few lines up in the method you will see something similar to this:
invoke-virtual {v0, v9, v5}, Landroid/content/Context;->getString(I[Ljava/lang/ObjectLjava/lang/String;
move-result-object v5
What that is doing is using getString to get the date and moving it into the register v5. This v5 is then used in our setText call.
So now we have identified our text view in the smali we can use setTextColor to change its color.
A bit of background is useful here. Color pickers do not act directly on any smali. Your phone has a database where it stores its settings. It is located in data/data/com.android.providers.settings/databases/settings.db. You can open it with Root Explorer and take a look. You will see a standard database with entries and values. What color picker code does is put an entry in this database with a “key” and a hex code. The smali then uses this key to look up the hex color it needs to set.
Now we need to add some code to look up that entry and return the color to the smali. There are 3 elements to this:
The ContentResolver
This is used to resolve the entry in the database. In order to use the content resolver we must put it into a register as we mentioned earlier. At the top of the method you will see .locals X where X is a number. This is the number of registers used in the method. So if it says .locals 5 there will be v0,v1,v2,v3 and v4. We need to add 3 to this value as we will be using 3 new registers. One for the resolver, one for the default color (in case there is no entry in the database it needs to have a color to set) and one for the key.
Now we need context in order to get the content resolver. There are a few ways to do this. A lot of files have a field called mContext. This can be used directly like this:
iget-object v5, p0, Lcom/android/systemui/statusbar/policy/BrightnessController;->mContext:Landroid/content/Context;
This is using iget-object to put mContext into v5. As mentioned earlier the p0 mean “this”.
The v5 should be the first of the new registers you added. So if previously .locals was 5 and you changed it to 8 then this would be v5 as v0 to v4 already exist. You can reuse registers but you can run into problems if it is needed further through the code so it is advisable to add new.
Alternatively, smali files whose .super is a view (look at the top of the smali for .super) like the date view we are working with here can use getcontext to get context like this:
invoke-virtual {p0}, Lcom/android/systemui/statusbar/policy/DateView;->getContext()Landroid/content/Context;
move-result-object v5
Now we have context we can use it to get the content resolver and put it into the register using this line:
invoke-virtual {v5}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v5
The Key
Next we need the key that we want to look up in the database. This is as simple as :
const-string v6, "date_color"
This just puts the constant string “date_color” into v6. The text inside the “” can be anything you like but cannot have spaces and the key must match the picker key we will add later.
The Default Value
Next we need a default color for in case there is no entry in the database. For example on a fresh install or after a wipe. The value is hex but in reverse preceded with -0x so ICS blue 33b5e5 becomes -0xcc4a1a because 0 = F, 1 = E, 2 = D etc
0 = F
1 = E
2 = D
3 = C
4 = B
5 = A
6 = 9
7 = 8
8 = 7
9 = 6
A = 5
B = 4
C = 3
D = 2
E = 1
F = 0
We put that into our 3rd new register v7 using:
const v7, -0xcc4a1a
Now we have all the needed elements we can use them to return the color to the smali from the database using:
invoke-static {v5, v6, v7}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v5
This uses the getInt method with our parameters. I have colored them so you can see how the registers relate to the getInt method. V5 is the content resolver, v6 is the string and v7 is the integer of the color.
The resultant color from the database is then moved into v5. We can use v5 register again as we no longer need the content resolver.
The color from the database is now stored in v5. From the settext line we found earlier we can see that the text view is referred to as p0:
invoke-virtual {p0, v5}, Lcom/android/systemui/statusbar/policy/DateView;->setText(Ljava/lang/CharSequenceV
The first item in the brackets is the text view. This wont be p0 in all cases. Its only p0 here because we are working with a smali that has a view as its super so the smali is effectively the text view. If working with something like ToggleSlider for example we may have something like:
invoke-virtual {v2, v3}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequenceV
So in this case the text view is in v2.
We can now use setTextColor on our date which is p0 with the color which we put in v5:
invoke-virtual {p0, v5}, Lcom/android/systemui/statusbar/policy/DateView;->setTextColor(I)V
The full code looks like this:
invoke-virtual {p0, v3}, Lcom/android/systemui/statusbar/policy/DateView;->setText(Ljava/lang/CharSequenceV
invoke-virtual {p0}, Lcom/android/systemui/statusbar/policy/DateView;->getContext()Landroid/content/Context;
move-result-object v5
invoke-virtual {v5}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v5
const-string v6, "date_color"
const v7, -0xcc4a1a
invoke-static {v5, v6, v7}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v5
invoke-virtual {p0, v5}, Lcom/android/systemui/statusbar/policy/DateView;->setTextColor(I)V
Oh and just so you know the big V at the end of lines like ;->setText(Ljava/lang/CharSequenceV and ;->setTextColor(I)V means the method returns void or nothing.
Hopefully the apk will now compile and you can test the result. In order for something to change immediately you need observers but I wont go into that here. This will only change when the updateClock method runs. A reboot will also trigger it to update the color.
I know I have written a lot to take in here. But hopefully this will give you a good basic understanding of how methods are called with parameters in smali.
Next stop…..choosing the color!
Thanks to ficeto this part is REALLY easy!
Decompile the attached apk. You will find a file called preferences.xml in the xml folder. Open it with Notepad++. Each instance of this line will add another picker…
<com.ficeto.colorpicker.ColorPickerPreference android:title="Dropdown Date Color" android:key="date_color" android:summary="Select Color" android:dialogTitle="Select Color" />
Change the android:title to what you want your picker to be called and change android:key=“date_color” to whatever the key you used earlier was. So if your smali was....
const-string v6, "clock_color"
Then the android:key would be “clock_color”.
That’s it. Compile and push the apk or install as a system app and it will show in your app drawer as custom settings. Now go test your new mod!!
Any questions or problems please ask (with logs and files if possible) as its impossible to cover all eventualities in a guide.
OK....time for part 2
COLORING IMAGES
This part will cover two things. Coloring images in a similar way to setting text colors from part 1 and also how to create a method and pass it context. Sometimes you wont be able to use mContext or getcontext but most smali files have context already in their init so you can use that and pass it to a new method. Using your own method is more efficient as you can run your code to get the color from the database just once and use it on multiple items and in multiple places.
There are three main ways to color an image. Using the method setColorFilter(I)V which is in android/widget/ImageView smali in framework2.jar, using method public final setColorFilter(ILandroid/graphics/PorterDuff$ModeV in the same file and using method public setColorFilter(ILandroid/graphics/PorterDuff$ModeV in android/graphics/drawable/Drawable smali in framework.jar. It depends what and where the image is as to which you use. All three methods overlay a color on an existing image and the two with porterduffmode have a means of choosing what effect the overlay has. There is more about this at the bottom of the post.
Lets start....
Things are stored in fields in a smali. At the top of the file you will see them like this:
Code:
.field protected mType:Ljava/lang/String;
.field protected mView:Landroid/view/View;
.field protected mIcon:I
These fields can be used to store things of their type. So in the ones shown above you would put a string, a view and an integer respectively. You can see the type a field should hold after the :
In order to use your own method to get the color from the database we need to add a new field to store the value in so we can use it in another method. For this example i am going to use the toggle icons in lidroids toggle mod but this can be done on pretty much any image you want.
At the top of the smali with the other instance fields add your new field. You can call it whatever you want and it is going to store an integer so you will need an I after the colon. Im calling this one mToggleColor for obvious reasons:
Code:
.field private mToggleColor:I
We now have somewhere to put our value so now we can write the new method. At this point you should refer to the text color guide for explanations about the content resolver, context and registers as I will assume you have an idea about these now.
You can call your method anything you want. It will need 3 registers to store the resolver, default value and integer. This method has no context parameter (in the brackets after the method name) so you would need to use getcontext or mContext....
Code:
.method color_toggles()V
.locals 3
If you are going to use existing context and pass it to your method it would look like this. As you can see the method is expecting context as its parameter when called...
Code:
.method color_toggles(Landroid/content/Context;)V
.locals 3
Now we get the content resolver so we need context. If using the first method then you would need to call your view and invoke getcontext like this in stock toggles:
Code:
iget-object v1, p0, Lcom/android/systemui/statusbar/policy/quicksetting/QuickSettingButton;->mBtnImage:Landroid/widget/ImageView;
invoke-virtual {v1}, Landroid/widget/ImageView;->getContext()Landroid/content/Context;
move-result-object v1
invoke-virtual {v1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v1
As metioned in the text color guide your contentresolver is now in v1.
If you are passing context to your method then the context is the parameter of the method. Each item in brackets after methods name is stored in a p. So in this case the context would be in p1. All you need to do is use it to get the resolver:
Code:
invoke-virtual {p1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v1
Again...resolver now in v1.
The next part is identical to the text color guide so i wont repeat it. But you should have now something that looks like this:
Code:
.method color_toggles()V
.locals 3
iget-object v1, p0, Lcom/android/systemui/statusbar/policy/quicksetting/QuickSettingButton;->mBtnImage:Landroid/widget/ImageView;
invoke-virtual {v1}, Landroid/widget/ImageView;->getContext()Landroid/content/Context;
move-result-object v1
const-string v2, "theme_color"
const v3, -0x4d06ff
invoke-static {v1, v2, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v1
or if passing context:
Code:
.method color_toggles(Landroid/content/Context;)V
.locals 3
invoke-virtual {p1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v1
const-string v2, "theme_color"
const v3, -0xcc4a1a
invoke-static {v1, v2, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v1
Both of the above now have your color stored in v1. We can now put it into your new field that you created earlier using iput:
Code:
iput v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mToggleColor:I
This puts the integer in v1 into the field in p0 (this file) and stores it as mToggleColor
Your method is not expected to return anything meaning something doesnt call it and ask for a value in reply so after this we need:
Code:
return-void
....and then to finish the method....
Code:
.end method
The final methods look like this:
Code:
.method color_toggles()V
.locals 3
iget-object v1, p0, Lcom/android/systemui/statusbar/policy/quicksetting/QuickSettingButton;->mBtnImage:Landroid/widget/ImageView;
invoke-virtual {v1}, Landroid/widget/ImageView;->getContext()Landroid/content/Context;
move-result-object v1
const-string v2, "theme_color"
const v3, -0x4d06ff
invoke-static {v1, v2, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v1
iput v1, p0, Lcom/android/systemui/statusbar/policy/quicksetting/QuickSettingButton;->mToggleColor:I
return-void
.end method
Code:
.method color_toggles(Landroid/content/Context;)V
.locals 3
invoke-virtual {p1}, Landroid/content/Context;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v1
const-string v2, "theme_color"
const v3, -0xcc4a1a
invoke-static {v1, v2, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v1
iput v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mColor:I
return-void
.end method
Now your color can be put into your new field we need to invoke your new method. Otherwise it will just be an empty field. You can do this in a number of places. Either directly before you use it or in the methods init. We will come back to this.
In order to color an image you need to find it first. There are ways of calling the image by its id but looking for it this way will familiarise you more with smali. Images can be set using setImageResource and setImageDrawable. If you search firstly for the images id in the smalis to find the correct file and if that doesnt find anything then have a look at file names and see what you can find that looks like it might be right. In this case PowerButton smali has a method called :
Code:
.method private updateImageView(II)V
...which uses setImageResource(I)V. Sounds like a good place to start!
Code:
.method private updateImageView(II)V
.locals 2
iget-object v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v1, p1}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/ImageView;
invoke-virtual {v0, p2}, Landroid/widget/ImageView;->setImageResource(I)V
return-void
.end method
We need to invoke your new method. If you are not passing context you can just do this:
Code:
invoke-virtual {p0}, Lcom/android/systemui/statusbar/policy/quicksetting/QuickSettingButton;->color_toggles()V
...which will invoke your new method and put your color in your field.
Or to pass context you would do:
Code:
invoke-virtual {v1}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v1
invoke-virtual {p0, v1}, Lcom/alliance/systemui/quickpanel/PowerButton;->color_toggles(Landroid/content/Context;)V
In the above code the method you are in has a Landroid/view/View; stored in v1. You can use getContext on this and then invoke your method. The invoke says to call your method color_toggles(Landroid/content/ContextV which is in this file (p0) with the parameter v1 (the context). Now your method has run we can use iget to get the color from the field:
Code:
iget v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mColor:I
You can see in the original updateImage method that the imageView is in v0. We can now apply the color (in v1) to the image (v0).
Code:
invoke-virtual {v0, v1}, Landroid/widget/ImageView;->setColorFilter(I)V
Final methods would look like this:
Code:
.method private updateImageView(II)V
.locals 2
invoke-virtual {p0}, Lcom/android/systemui/statusbar/policy/quicksetting/QuickSettingButton;->color_toggles()V
iget-object v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v1, p1}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/ImageView;
invoke-virtual {v0, p2}, Landroid/widget/ImageView;->setImageResource(I)V
iget v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mColor:I
invoke-virtual {v0, v1}, Landroid/widget/ImageView;->setColorFilter(I)V
return-void
.end method
or
Code:
.method private updateImageView(II)V
.locals 2
iget-object v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v1, p1}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/ImageView;
invoke-virtual {v0, p2}, Landroid/widget/ImageView;->setImageResource(I)V
invoke-virtual {v1}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v1
invoke-virtual {p0, v1}, Lcom/alliance/systemui/quickpanel/PowerButton;->color_toggles(Landroid/content/Context;)V
iget v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mColor:I
invoke-virtual {v0, v1}, Landroid/widget/ImageView;->setColorFilter(I)V
return-void
.end method
Your source image should be white. You can make them semi transparent so the color is not as bright. For example the off toggles could be 50% transparent so they will only appear dim compared to the on ones.
You will notice in PowerButton smali there is another method....
Code:
.method private updateImageView(ILandroid/graphics/drawable/Drawable;)V
.locals 2
iget-object v1, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v1, p1}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object v0
check-cast v0, Landroid/widget/ImageView;
invoke-virtual {v0, p2}, Landroid/widget/ImageView;->setImageDrawable(Landroid/graphics/drawable/Drawable;)V
return-void
.end method
This is the same except it uses 2 parameters (in the brackets after the name) of and (I)nteger and Landroid/graphics/drawable/Drawable rather than two (I)ntegers.
You don't HAVE to use your own method. You could just use identical code to the textColor code straight after the setImageResource and invoke setColorFilter on the ImageView rather than setTextColor on a TextView. But I think it is good practice to use a new method
PorterDuffMode
Sometimes when you implement a color picker you will get an outcome you dont want like a battery that had a a white centre and the fill in a color wouldnt show the level as it would all have the same color overlay. Instead of using setColorFilter(I)V you can use setColorFilter(ILandroid/graphics/PorterDuff$ModeV.
If you are familiar with Photoshop you may be better than me at this but basically it changes the way the color is laid over. Using different modes will give different results. As Im not great with Photoshop for me its more trial and error!
There are lots of different modes:
PorterDuff.Mode ADD Saturate(S + D)
PorterDuff.Mode CLEAR [0, 0]
PorterDuff.Mode DARKEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]
PorterDuff.Mode DST [Da, Dc]
PorterDuff.Mode DST_ATOP [Sa, Sa * Dc + Sc * (1 - Da)]
PorterDuff.Mode DST_IN [Sa * Da, Sa * Dc]
PorterDuff.Mode DST_OUT [Da * (1 - Sa), Dc * (1 - Sa)]
PorterDuff.Mode DST_OVER [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc]
PorterDuff.Mode LIGHTEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]
PorterDuff.Mode MULTIPLY [Sa * Da, Sc * Dc]
PorterDuff.Mode OVERLAY
PorterDuff.Mode SCREEN [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
PorterDuff.Mode SRC [Sa, Sc]
PorterDuff.Mode SRC_ATOP [Da, Sc * Da + (1 - Sa) * Dc]
PorterDuff.Mode SRC_IN [Sa * Da, Sc * Da]
PorterDuff.Mode SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)]
PorterDuff.Mode SRC_OVER [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc]
PorterDuff.Mode XOR [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
The letters in CAPITALS are the what you put as the parameter.
I have found that MULTIPLY is the most useful. SRC_ATOP is used as default in setColorFilter(I)V
To use one you need to put the mode into a register. You do that using sget:
Code:
sget-object v1, Landroid/graphics/PorterDuff$Mode;->MULTIPLY:Landroid/graphics/PorterDuff$Mode;
Then you call the porterduff setcolorfilter method instead of the normal one. Like this:
invoke-virtual {v6, v12, v1}, Landroid/widget/ImageView;->setColorFilter(ILandroid/graphics/PorterDuff$ModeV
...instead of this:
invoke-virtual {v6, v12}, Landroid/widget/ImageView;->setColorFilter(I)V
There is a good article here
Please ask if anything is unclear.
Toggles
You have learnt how to get a value from the database creating a toggle is pretty straightforward. For this example I will use toggling the text on lidroid toggles but you can use this on anything from settings button in statusbar to things stopping auto scroll on toggles etc.
Again we start by finiding the method we need to mod. Look at the top of smali files for the field names. This may help you to find the item you wish to toggle. Method names will also help you find your place. In this example we can see in PowerButton smali there is a method called:
Code:
.method protected updateText()V
Obvious huh! It wont always be that easy to find so i will cover how to call something by it's ID later in this post.
In this method you can see that the text is set by calling the setText method. There are two ways to do this. The obvious thing to do is not to run this line so the text will not be set. This is the first way i will cover and it is the way that things are toggled such as ink effect or crt etc rather than showing/hiding things. I will get to that later.
TURNING THINGS ON/OFF
We need to read that value into our smali. This is done in exactly the same way as a color so if you are not sure please go back and read those posts.
This would be added the line before the setText call....
Code:
iget-object v3, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v3}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v3
...dont forget to add to .locals if you are using a new register!! That gets us context so now we can...
Code:
const-string v4, "toggle_text"
const v5, 0x1
invoke-static {v3, v4, v5}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
...which gets the value from the database which will be 1 or 0 for on/off and puts it into v3.
To toggle something we then act on that value. The if-nez checks if a value is non-zero. So the next line would be:
Code:
if-nez v3, :cond_skip_text
....as you can see, if v3 is non-zero then it goes to the condition skip_text.
All we need to do now is make a new cond called skip_text after the setText line so it effectively does just that.....skips the setText. Right before return-void put:
Code:
:cond_skip_text
That's it. All you have to do with a toggle to turn something on or off is skip the chunk of text that does what you want to stop. So as long as your new cond comes after it then it should work
SHOWING/HIDING
This works in exactly the same way as above but instead of skipping code you are going to use setVisibility(I)V method.
We have got the value from the database as we did before:
Code:
iget-object v3, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v3}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v3
const-string v4, "toggle_text"
const v5, 0x1
invoke-static {v3, v4, v5}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
if-nez v3, :cond_show_text
To hide something we must set visibility of the item to "gone". The value for this is 0x8. Visible is 0x1. If the database value returns 0 then the item is unchecked and so should be hidden. If it returns 1 then the item should be visible.
If the value from the database was 1 and the checkbox was ticked then you can use the value in v3 as the value for setVisibility. If it was 0 then the value needs to be set to 0x8 for "gone". We can put 0x8 into v4 here because the line will be skipped if the checkbox was checked:
Code:
const v3, 0x8
....now we add the new cond:
Code:
:cond_show_text
and invoke the set visibility which now has either 0x1 or 0x8 in it.
Code:
invoke-virtual {v1, v3}, Landroid/widget/TextView;->setVisibility(I)V
This tells the code to find the place labelled :goto_new so we add that straight after the code that sets visibility to shown. The full code would look like this....
Code:
iget-object v3, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v3}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v3
const-string v4, "toggle_text"
const v5, 0x1
invoke-static {v3, v4, v5}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
if-nez v3, :cond_show_text
const v4, 0x8
:cond_show_text
invoke-virtual {v1, v4}, Landroid/widget/TextView;->setVisibility(I)V
Thats it!
CALLING THINGS BY ID
Say you wanted to make a show/hide for the recents button that can be added to dropdown header. You can call it by it's public ID and then use setvisibility. Create a new method like you did for coloring images (refer to that guide if unsure), get a value from the database, test for non-zero and skip to cond. You can use mCcontext here from in Phonestatusbar:
Code:
.method Update_recents()V
.locals 6
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 v1
const-string v2, "recents_button"
const/4 v3, 0x1
invoke-static {v1, v2, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
if-nez v3, :cond_1
const v3, 0x8
Now to get the image we can use findViewById method. In order to use it we need the parent view that contains the image. In Phonestatusbar you can get to most stuff by using the field mStatusBarWindow.
Code:
iget-object v4, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mStatusBarWindow:Lcom/android/systemui/statusbar/phone/StatusBarWindowView;
Now we get the id of the image from public.xml and put it into a register:
Code:
const v5, 0x7f0d0014
....and then findViewById. This method expects an integer as a parameter which we have in v5...
Code:
invoke-virtual {v4, v5}, Lcom/android/systemui/statusbar/phone/StatusBarWindowView;->findViewById(I)Landroid/view/View;
move-result-object v4
Now we have the item we can setVisibility with the value in v3:
Code:
:cond_1
invoke-virtual {v4, v3}, Landroid/widget/LinearLayout;->setVisibility(I)V
In this case I used LinearLayout but you can use imageView or whatever depending what you are doing. The full method would look like this:
Code:
.method Update_recents()V
.locals 6
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 v1
const-string v2, "recents_button"
const/4 v3, 0x1
invoke-static {v1, v2, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
if-nez v3, :cond_1
const/4 v3, 0x8
:cond_1
iget-object v5, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mStatusBarWindow:Lcom/android/systemui/statusbar/phone/StatusBarWindowView;
const v6, 0x7f0d0014
invoke-virtual {v5, v6}, Lcom/android/systemui/statusbar/phone/StatusBarWindowView;->findViewById(I)Landroid/view/View;
move-result-object v4
invoke-virtual {v4, v3}, Landroid/widget/LinearLayout;->setVisibility(I)V
return-void
.end method
All we need to do now is to call the method. The best place for this is during makestatusbarview. I put it right after the settings button is set but you can put it in loads of places. It just invokes update_recents_button in p0 (this file):
Code:
iget-object v9, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mSettingsButton:Landroid/widget/ImageView;
iget-object v10, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mSettingsButtonListener:Landroid/view/View$OnClickListener;
invoke-virtual {v9, v10}, Landroid/widget/ImageView;->setOnClickListener(Landroid/view/View$OnClickListener;)V
[COLOR="Red"] invoke-virtual {p0}, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->update_recents_button()V[/COLOR]
Thats all for now
USEFUL POSTS:
NOTEPAD++ SMALI HIGHLIGHTING - Thanks to @majdinj
LIST OF DALVIK OPCODES - Thanks to @majdinj
Goldie said:
Toggles
You have learnt how to get a value from the database creating a toggle is pretty straightforward. For this example I will use toggling the text on lidroid toggles but you can use this on anything from settings button in statusbar to things stopping auto scroll on toggles etc.
Again we start by finiding the method we need to mod. Look at the top of smali files for the field names. This may help you to find the item you wish to toggle. Method names will also help you find your place. In this example we can see in PowerButton smali there is a method called:
Code:
.method protected updateText()V
Obvious huh! It wont always be that easy to find so i will cover how to call something by it's ID later in this post.
In this method you can see that the text is set by calling the setText method. There are two ways to do this. The obvious thing to do is not to run this line so the text will not be set. This is the first way i will cover and it is the way that things are toggled such as ink effect or crt etc rather than showing/hiding things. I will get to that later.
TURNING THINGS ON/OFF
We need to read that value into our smali. This is done in exactly the same way as a color so if you are not sure please go back and read those posts.
This would be added the line before the setText call....
Code:
iget-object v3, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v3}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v3
...dont forget to add to .locals if you are using a new register!! That gets us context so now we can...
Code:
const-string v4, "toggle_text"
const v5, 0x1
invoke-static {v3, v4, v5}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
...which gets the value from the database which will be 1 or 0 for on/off and puts it into v3.
To toggle something we then act on that value. The if-nez checks if a value is non-zero. So the next line would be:
Code:
if-nez v3, :cond_skip_text
....as you can see, if v3 is non-zero then it goes to the condition skip_text.
All we need to do now is make a new cond called skip_text after the setText line so it effectively does just that.....skips the setText. Right before return-void put:
Code:
:cond_skip_text
That's it. All you have to do with a toggle to turn something on or off is skip the chunk of text that does what you want to stop. So as long as your new cond comes after it then it should work
SHOWING/HIDING
This works in exactly the same way as above but instead of skipping code you are going to use setVisibility(I)V method.
We have got the value from the database as we did before:
Code:
iget-object v3, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v3}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v3
const-string v4, "toggle_text"
const v5, 0x1
invoke-static {v3, v4, v5}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
if-nez v3, :cond_show_text
To hide something we must set visibility of the item to "gone". The value for this is 0x8. Visible is 0x1. If the database value returns 0 then the item is unchecked and so should be hidden. If it returns 1 then the item should be visible.
If the value from the database was 1 and the checkbox was ticked then you can use the value in v3 as the value for setVisibility. If it was 0 then the value needs to be set to 0x8 for "gone". We can put 0x8 into v4 here because the line will be skipped if the checkbox was checked:
Code:
const v3, 0x8
....now we add the new cond:
Code:
:cond_show_text
and invoke the set visibility which now has either 0x1 or 0x8 in it.
Code:
invoke-virtual {v1, v3}, Landroid/widget/TextView;->setVisibility(I)V
This tells the code to find the place labelled :goto_new so we add that straight after the code that sets visibility to shown. The full code would look like this....
Code:
iget-object v3, p0, Lcom/alliance/systemui/quickpanel/PowerButton;->mView:Landroid/view/View;
invoke-virtual {v3}, Landroid/view/View;->getContext()Landroid/content/Context;
move-result-object v3
const-string v4, "toggle_text"
const v5, 0x1
invoke-static {v3, v4, v5}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
if-nez v3, :cond_show_text
const v4, 0x8
:cond_show_text
invoke-virtual {v1, v4}, Landroid/widget/TextView;->setVisibility(I)V
Thats it!
CALLING THINGS BY ID
Say you wanted to make a show/hide for the recents button that can be added to dropdown header. You can call it by it's public ID and then use setvisibility. Create a new method like you did for coloring images (refer to that guide if unsure), get a value from the database, test for non-zero and skip to cond. You can use mCcontext here from in Phonestatusbar:
Code:
.method Update_recents()V
.locals 6
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 v1
const-string v2, "recents_button"
const/4 v3, 0x1
invoke-static {v1, v2, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
if-nez v3, :cond_1
const v3, 0x8
Now to get the image we can use findViewById method. In order to use it we need the parent view that contains the image. In Phonestatusbar you can get to most stuff by using the field mStatusBarWindow.
Code:
iget-object v4, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mStatusBarWindow:Lcom/android/systemui/statusbar/phone/StatusBarWindowView;
Now we get the id of the image from public.xml and put it into a register:
Code:
const v5, 0x7f0d0014
....and then findViewById. This method expects an integer as a parameter which we have in v5...
Code:
invoke-virtual {v4, v5}, Lcom/android/systemui/statusbar/phone/StatusBarWindowView;->findViewById(I)Landroid/view/View;
move-result-object v4
Now we have the item we can setVisibility with the value in v3:
Code:
:cond_1
invoke-virtual {v4, v3}, Landroid/widget/LinearLayout;->setVisibility(I)V
In this case I used LinearLayout but you can use imageView or whatever depending what you are doing. The full method would look like this:
Code:
.method Update_recents()V
.locals 6
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 v1
const-string v2, "recents_button"
const/4 v3, 0x1
invoke-static {v1, v2, v3}, Landroid/provider/Settings$System;->getInt(Landroid/content/ContentResolver;Ljava/lang/String;I)I
move-result v3
if-nez v3, :cond_1
const/4 v3, 0x8
:cond_1
iget-object v5, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mStatusBarWindow:Lcom/android/systemui/statusbar/phone/StatusBarWindowView;
const v6, 0x7f0d0014
invoke-virtual {v5, v6}, Lcom/android/systemui/statusbar/phone/StatusBarWindowView;->findViewById(I)Landroid/view/View;
move-result-object v4
invoke-virtual {v4, v3}, Landroid/widget/LinearLayout;->setVisibility(I)V
return-void
.end method
All we need to do now is to call the method. The best place for this is during makestatusbarview. I put it right after the settings button is set but you can put it in loads of places. It just invokes update_recents_button in p0 (this file):
Code:
iget-object v9, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mSettingsButton:Landroid/widget/ImageView;
iget-object v10, p0, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->mSettingsButtonListener:Landroid/view/View$OnClickListener;
invoke-virtual {v9, v10}, Landroid/widget/ImageView;->setOnClickListener(Landroid/view/View$OnClickListener;)V
[COLOR="Red"] invoke-virtual {p0}, Lcom/android/systemui/statusbar/phone/PhoneStatusBar;->update_recents_button()V[/COLOR]
Thats all for now
Click to expand...
Click to collapse
Hi Goldie hope you are safe and well.
I have been looking at your guide and cant for the life of me work out what to put where, you have helped me out in the past with themeing queries and i was hoping you could help me with a smali issue.
I would like to hide a button/option in an app that is called from a smali file, would it be at all possible that you could add the nessasery lines to the smali for me to reference against the original to give me a better understanding of your guide and smali in general. Hope you can help, if you can i will attatch the smali file and explain what i am trying to achive.
Thanks in advanced.