Related
Hi,
for cyanogen5Beta4 I have a services.jar with white text at notification bar.
Now I have the new MoDaCo release and there is the text black.
I want white text.
this text is in the services.jar
Could anybody help me and explain, how to configure this services.jar to get white text instead of black text.
Thank you!
You need to run the colorchanger on it. Every rom is different pretty much. You need to do that every time you change the colors of the text.
This is how enomther (so all credit goes to him) explained to me on how to change it.
You can get smali/baksmali here.
I use PSPad to edit the files in windows. I right click and select open with PSPad.
Once you crack open services.jar/classes.dex with baksmali ....there are (2) files of concern, the first is com/android/server/status/StatusBarIcon.smali ... locate this file and open it up and search for ...
Code:
invoke-virtual {v4, v6}, Landroid/widget/TextView;->setTextColor(I)V
Above that line (2 lines up) ... you'll see ...
Code:
const/high16 v6, -0x100
That's black .. change to ...
Code:
const v6, -0x1
That's white ... this is a simply color change and easier since invoke-virtual is going to give us color out right ... we just have to change the color.
Then locate file ... com/android/server/status/com/android/server/status/StatusBarService.smali
There are (3) lines you need to search for here ... now they don't have inherent color change properties anymore ... which is why colorChange.jar is jacked up for you.
The threes lines to search for (and yes they are each in different places of the file) ... are ...
Code:
iput-object v7, p0, Lcom/android/server/status/StatusBarService;->mDateView:Lcom/android/server/status/DateView;
iput-object v7, p0, Lcom/android/server/status/StatusBarService;->mSpnLabel:Landroid/widget/TextView
iput-object v7, p0, Lcom/android/server/status/StatusBarService;->mPlmnLabel:Landroid/widget/TextView;
Again, since these are iput-object calls ... there's no inherent color changing properties ....
You must add the (2) color change lines above each of these lines ... the first lines set a variable for the color value (which in the example) ... the second line forces the text to that color with a call to setTextColor(). So when you're done ... those three lines will be 9 lines (3 lines in 3 seperate places in the file) ... as such ...
Code:
const v8, -0x1
invoke-virtual {v7, v8}, Landroid/widget/TextView;->setTextColor(I)V
iput-object v7, p0, Lcom/android/server/status/StatusBarService;->mDateView:Lcom/android/server/status/DateView;
Code:
const v8, -0x1
invoke-virtual {v7, v8}, Landroid/widget/TextView;->setTextColor(I)V
iput-object v7, p0, Lcom/android/server/status/StatusBarService;->mSpnLabel:Landroid/widget/TextView;
Code:
const v8, -0x1
invoke-virtual {v7, v8}, Landroid/widget/TextView;->setTextColor(I)V
iput-object v7, p0, Lcom/android/server/status/StatusBarService;->mPlmnLabel:Landroid/widget/TextView;
See how we're now setting a color variable and calling invoke-virtual prior to iput-object? ... that's the magic.
Save all that up and then run smali ... reinsert your classes.dex ... and you should be all set.
~enom~
Click to expand...
Click to collapse
Oh holy....
Wow, okay. Thank you both for reply.
Now I've been looking for an english teacher who can help me....
OK, it looks awesome. I wanna look to do what I can!
Thank you again!
Hah, I can't get it.
I've downloaded this three programms, but nothing works really.
Baksmali.jar doesn't start.
I've got an windows machine....
OK, some things I did now.
Thanks for your help.
But the clock on the upper right corner is black anymore.
If somebody could give me a tipp please.
I now have checked it twice, but can't find my failure.
The other things are quite white. They work, only the clock...
david1171 said:
This is how enomther (so all credit goes to him) explained to me on how to change it.
You can get smali/baksmali here.
I use PSPad to edit the files in windows. I right click and select open with PSPad.
Click to expand...
Click to collapse
Isn't that what the colorchanger does automatically? Not arguing or anything, but holy **** that looks complicated! I just use the colorchanger on my morphs...
Colorchanger?
You make me smile... Any Link to this?
Formel-LMS said:
Colorchanger?
You make me smile... Any Link to this?
Click to expand...
Click to collapse
File available here
Rename the file to just colorchangev3.jar (or something shorter if you prefer. I use cc3.jar personally)
You will need the java jdk set up on your computer. I made a pretty in-depth thread on this subject over on AOD
If you have any questions on it, hit me up. Preferably over there since I check it more often than here.
Thank you for your reply. I'm coming over to you. Now, I've take my first look.
im trying to do this on a galaxy s... is there something I am doing wrong... I did the first change... changing anything with the other three lines throws a forceclose loop upon reboot
any thoughts?
Go to the end of the post for the flashable zips.
===================================
By default the user can set as minimum brightness level 30 (over 255) from the settings, 20 sliding the finger on the status bar.
Files changed:
/system/framework/services.jar
/system/app/Settings.apk
/system/app/SystemUI.apk (UPDATE 5. I completely forgot to add this in the guide)
(I used KPU as reference)
How to mod services.jar:
You need java installed and smali.jar/baksmali.jar. There are probably tools that can help you or you can look for a better explanation on how to do it. (this tutorial is not about smali/baksmali).
Here what I usually do:
1) Extract classes.dex from it (jar files are simply zip files, use any file archiver to do that)
2) Decompile classes.dex with this command (from cmd/shell etc):
Code:
java -jar baksmali.jar classes.dex -o classout
This will create a directory (classout) with all the .smali files in it. Make all the changes you need to do.
3) Recompile classes.dex with this command:
Code:
java -Xmx512M -jar smali.jar classout -o new-classes.dex
This command will recreate the .dex file (named new-classes.dex).
4) Rename new-classes.dex to classes.dex and put it back inside services.jar (overwrite the existing one).
services.jar
1) Decompile services.jar and open com/android/server/PowerManagerService.smali
2) Look for:
Code:
const/16 v4, 0x14
(line 10727). 0x14 is the hexadecimal of 20. This is the minimum brightness level achievable. You should use something greater than or equal to 1.
Code:
const/16 v4, [B]0x1[/B]
If you want, you can test some values. You simply need to run:
Code:
echo 1 > /sys/class/backlight/omap_bl/brightness
where 1 is the backlight value (1/255):
3) Look for:
Code:
const/16 v2, 0x14
(line 2189).
If you don't change this value you'll be able to decrease your backlight below 20, but if you turn the screen off and then on, it is automatically set to this value. Use the same value above.
Code:
const/16 v2, [B]0x1[/B]
UPDATE 1:
When the phone is inactive, before the screen is switched off, the backlight value is automatically set to 20. The problem is that if you can go lower to that value, when inactive, instead of decreasing, the brightness increase. To avoid this
4) Look for:
UPDATE 4: (if current brightness is higher than 20/255, use the default dim value):
Code:
.restart local [COLOR="Red"]v10[/COLOR] #nominalCurrentValue:I
(aound line 5859) and remember the "red" part (aka the register. It could be something different). Now look for:
Code:
const/16 v5, 0x14
and change it with
Code:
const/16 v5, 0x14
if-lt [COLOR="Red"]v10[/COLOR],v5,:low_dim
goto/16 :goto_a0
:low_dim
const/16 v5, 0x1
(line 5964). Make sure the red part is like the one above.
Pseudocode:
Code:
if your current brightness < 0x14 (20/255) => dim = 0x1 (1/255)
if your current brightness > 0x14 (20/255) => dim = 0x14 (20/255)
This value should be less than or equal to the values used above.
UPDATE 3:
When the battery is below 10, the brightness goes to the minimum value achievable. That could be a problem if you set a very low value, because everytime you turn off and then on the screen, you'll always need to increase the brightness, because the minimum value is good only in very dark places. To disable this feature:
5) Look for (line 1494):
Code:
.method private batteryIsLow()Z
Replace this: (UPDATE 3b)
Code:
.method private batteryIsLow()Z
.registers 3
.prologue
.line 1812
iget-boolean v0, p0, Lcom/android/server/PowerManagerService;->mIsPowered:Z
with this:
Code:
.method private batteryIsLow()Z
.registers 3
.prologue
.line 1812
const/4 v0, 0x0
return v0
iget-boolean v0, p0, Lcom/android/server/PowerManagerService;->mIsPowered:Z
Settings.apk
1) Decompile Settings.apk and open smali/com/android/settings/BrightnessPreference.smali
2) Look for 0x1e (3 occurences, lines: 318, 603 and 664) and change with 0x4 (the value used above)
Code:
line 318: const/16 v3, 0x1e
line 664: add-int/lit8 v0, p2, 0x1e
line 603: add-int/lit8 v3, v3, 0x1e
Code:
line 318: const/16 v3, [B]0x1[/B]
line 664: add-int/lit8 v0, p2, [B]0x1[/B]
line 603: add-int/lit8 v3, v3, [B]0x1[/B]
3) open smali/com/android/settings/BrightnessPreference$BrightnessObserver.smali
Look for 0x1e (line 98) and change it with 0x4
Code:
const/16 v3, 0x1e
Code:
const/16 v3, [B]0x1[/B]
UPDATE 5:
SystemUI.apk
1) Decompile SystemUI.apk and open smali/com/android/systemui/statusbar/StatusBarService.smali
2) Look for
Code:
.local v0, checkBrightNess:I
const/16 v1, 0x1e
(around line 404) and change it with
Code:
.local v0, checkBrightNess:I
const/16 v1, 0x1
This will let you achieve the minimum brightness level through the status bar.
AUTO BRIGHTNESS
If you want to change the auto brightness levels there's already a tutorial: Link
Probably you'll find this helpful.
Note that if you set a level below 20, if you don't mod services.jar when your phone is inactive, the brightness will go to 20.
Are you looking for a "night pack"? Read here
===================================
Flashable zips for DEODEXED only.
Do a nandroid backup!
SystemUI.apk is not included in these zips, sorry. You can't go below "30" from the status bar.
UPDATE 4:
If the current brightness is higher than 20/255, when inactive, the screen brighntess is set to 20 instead of 1.
XXKPU
If you don't like this mod, you can always restore the original files using these flashable zip:
DDKP3 stock
XXKPQ stock
XXKPU stock
or restore a nandroid backup of course.
UPDATE 3:
Brigthness won't change when battery goes below 10.
DDKP3
XXKPQ
XXKPU
UPDATE 2:
This time I used as minimum level 1 instead of 4, as shown in the guide. Even if they are close, the difference is significant. In order to avoid brightness increases, the brighntess is set to 1 when inactive.
DDKP3
XXKPQ
XXKPU
UPDATE 1:
This is for who downloaded the first version. It simply contains the stock framework.jar, because the change I made is not needed. This will not remove the mod. See the files below for that.
XXKPU framework.jar
nice work bro
loSconosciuto said:
By default the user can set as minimum brightness level 30 from the settings, 20 sliding the finger on the status bar.
Files changed:
/system/framework/services.jar
/system/framework/framework.jar
/system/app/Settings.apk
(I used KPU as reference)
services.jar
1) Decompile services.jar and open com/android/server/PowerManagerService.smali
2) Look for:
Code:
const/16 v4, 0x14
(line 10727). 0x14 is the hexadecimal of 20. This is the minimum brightness level achievable. I use this:
Code:
const/16 v4, [B]0x4[/B]
3) Look for const/16 v2, 0x14 (line 2189).
If you don't change this value you'll be able to decrease your backlight below 20, but if you turn the screen off and then on, it is automatically set to this value. Use the same value above.
Code:
const/16 v2, [B]0x4[/B]
framework.jar
1) Decompile framework.jar and open android/os/Power.smali
2) Look for:
Code:
.field public static final BRIGHTNESS_DIM:I = 0x14
This is the brighntess level used when the phone is inactive. I suggest you to set a value lower or equal to the values used above, otherwise the backlight will increase instead of decreasing (I'm not sure of that, I didn't try an higher value).
Code:
.field public static final BRIGHTNESS_DIM:I = [B]0x4[/B]
Settings.apk
1) Decompile Settings.apk and open smali/com/android/settings/BrightnessPreference.smali
2) Look for 0x1e (3 occurences, lines: 318, 603 and 664) and change with 0x4 (the value used above)
Code:
line 318: const/16 v3, 0x1e
line 664: add-int/lit8 v0, p2, 0x1e
line 603: add-int/lit8 v3, v3, 0x1e
Code:
line 318: const/16 v3, [B]0x4[/B]
line 664: add-int/lit8 v0, p2, [B]0x4[/B]
line 603: add-int/lit8 v3, v3, [B]0x4[/B]
3) open smali/com/android/settings/BrightnessPreference$BrightnessObserver.smali
Look for 0x1e (line 98) and change it with 0x4
Code:
const/16 v3, 0x1e
Code:
const/16 v3, [B]0x4[/B]
Here attached there's a CWM flashable zip. It's made for stock KPU.
ATTENTION: I didn't test it, do a nandroid backup!.
If you want to change the auto-brightness levels there's already a tutorial: http://forum.xda-developers.com/showthread.php?t=1235212
Click to expand...
Click to collapse
Trying it now.
God, u don't need to QUOTE the whole post :banghead:
Sent from my GT-I9003 using Tapatalk 2 Beta-5
thanks a lot! I'll try this for shure. Is it going to work only on KPU? I have stock gingerbread. DDKP3.
Good work...
Thanks for working upon this.
But i would suggest one can use Screenfliter app from Market. Its more elegant solution
.Har**** said:
Thanks for working upon this.
But i would suggest one can use Screenfliter app from Market. Its more elegant solution
Click to expand...
Click to collapse
ur screen filter app works only in SUPERAMOLED and AMOLED displays ! i had used it in the past and the screen just looks faded brown with the same brightness level ! with this tweak u can actually lower the real brightness leel ! i myself use this app called ROOTDIM its amazing lets u put shortcuts on the desktop with the brightness levels i kept night as 1 ! and its awesome !
.Har**** said:
Thanks for working upon this.
But i would suggest one can use Screenfliter app from Market. Its more elegant solution
Click to expand...
Click to collapse
Screenfilter does not reduce the brightness of the screen, it actually creates another darker layer (or something like that) so the screen is running at the same brightness but u see another darker layer on top...
The Dev in this thread is directly reducing the screen brightness itself obviously resulting in better battery life...
Thanks loSconosciuto for working on this..
Can some kind Soul make a CWM for KPQ & DK3 & post it? :thumbup: :beer:
☞★sent from drajax's Galaxy SL!!! *♂ツ Hit thanz if I helped!
ilcorsaronero said:
thanks a lot! I'll try this for shure. Is it going to work only on KPU? I have stock gingerbread. DDKP3.
Click to expand...
Click to collapse
It's better to mod Settings.apk and services.jar again.
drajax said:
Can some kind Soul make a CWM for KPQ & DK3 & post it? :thumbup: :beer:
☞★sent from drajax's Galaxy SL!!! *♂ツ Hit thanz if I helped!
Click to expand...
Click to collapse
I can do it when I have some spare time.
I made the flashable zips for XXKPQ and DDKP3. See the OP.
This time I used as minimum level 1 instead of 4, as shown in the guide. Even if they are close, the difference is significant and to avoid brightness increases, the brightness is set to 1 when inactive.
If you think it's too low, I could use again 4 as value or ignore the minimum value achievable and use a higher value for inactive status.
Clarification
loSconosciuto said:
UPDATE:
Backlight value when inactive:
4) Look for:
Code:
const/16 v2, 0x14
and change it with
Code:
const/16 v2, [B]0x4[/B]
(line 5964).
This value should be less than or equal to the values used above.
Click to expand...
Click to collapse
I think line 5964 reads const/16 v5, 0x14 and not const/16 v2, 0x14 as stated.
Oh thanks, I forgot to change this.
OP updated.
Confirmed to work on DDKP3. RootDim can achieve lower light level than this, this has got a good balance. Great.
Just wondering... is it possible to merge this fix and that one about phone not vibrating when fully charged? Like they did here for SGS2 http://forum.xda-developers.com/showthread.php?t=1070506 and http://forum.xda-developers.com/showpost.php?p=18900464&postcount=150? It would be the perfect "night pack" for i9003!!!
Another update. See the OP for the changes (in the guide there's a better explanation).
ilcorsaronero said:
Confirmed to work on DDKP3. RootDim can achieve lower light level than this, this has got a good balance. Great.
Just wondering... is it possible to merge this fix and that one about phone not vibrating when fully charged? Like they did here for SGS2 http://forum.xda-developers.com/showthread.php?t=1070506 and http://forum.xda-developers.com/showpost.php?p=18900464&postcount=150? It would be the perfect "night pack" for i9003!!!
Click to expand...
Click to collapse
Are you sure? I can set as minimum level 1 from the settings and sliding the finger on the statusbar (in this case is harder to set the brightness at 1). If you used the first version (the one made for KPU, not avaible anymore), you are allowed to set as minimum brightness 4 (I decided to do so).
Otherwise I think I did something wrong, I can't test all the flashable zips.
Regarding the notification:
I disabled it in a dirty way renaming
Code:
/system/media/audio/ui/TW_Battery_caution.ogg
to
Code:
/system/media/audio/ui/TW_Battery_caution.ogg.bak
You can do the same for Charger_Connection.ogg and TW_Low_Battery.ogg (the names are self explanatory).
Anyway I'll see the guide, thanks.
loSconosciuto said:
UPDATE 3:
When the battery is below 10, the brightness goes to the minimum value achievable. That could be a problem if you set a very low value, because everytime you turn off and then on the screen, you'll always need to increase the brightness, because the minimum value is good only in very dark places. To disable this feature:
5) Look for:
Code:
.method private batteryIsLow()Z
(line 1494) few lines below this you have:
Code:
if-nez v0, :cond_10
(line 1501). Add before this line this:
Code:
goto :cond_10
Click to expand...
Click to collapse
You mean add this line:
goto :goto_1
And will you please add a date in the title of the post whenever you update the OP...
Thanks man
pancit said:
You mean add this line:
goto :goto_1
And will you please add a date in the title of the post whenever you update the OP...
Thanks man
Click to expand...
Click to collapse
I think I should read multiple times the post before hitting "Submit Reply" . Anyway you mean goto :goto_11.
Thanks a lot!
I'm sorry if u consider this off topic..
There are 2 apps in the market ROOTDIM & SCREENDIM... Are these apps safe to use IN THE LONG RUN and which one's better .. The one using root or the one without...
They are pretty safe, & the best of those is Rootdim mate! IMHO! :thumbup:
☞★sent from drajax's Galaxy SL!!! *♂ツ Hit thanz if I helped!
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.
I've noticed that when I'm trying to send a picture through text, the phone compresses the picture to the point where it gets pixelated. It looks awful!
Has anyone had this problem? I'm using the stock camera app.
Sent from my SM-G900P using Tapatalk
Yeah ive notice this too. On my s3 there was a mod that sended the pictures uncompressed. Hopefully we get that on this phone.
Sent from my SM-G900P using XDA Free mobile app
8sms! You can chose how big the picture is also allows MMS over wifi!
Sent from a Galaxy 5 light years away
Send via email no compression
Joe0113 said:
8sms! You can chose how big the picture is also allows MMS over wifi!
Sent from a Galaxy 5 light years away
Click to expand...
Click to collapse
Great find! Where do I change to allow MMS over WiFi? Is that the messaging limit?
Found the setting, but it still is compressing the image
Sent from my SM-G900P using Tapatalk
zune70 said:
Yeah ive notice this too. On my s3 there was a mod that sended the pictures uncompressed. Hopefully we get that on this phone.
Sent from my SM-G900P using XDA Free mobile app
Click to expand...
Click to collapse
What was that mod called for the s3? I'd like to follow the thread in case the developer decides to make one for this phone.
Sent from my SM-G900P using Tapatalk
slickdealers said:
What was that mod called for the s3? I'd like to follow the thread in case the developer decides to make one for this phone.
Sent from my SM-G900P using Tapatalk
Click to expand...
Click to collapse
http://forum.xda-developers.com/showthread.php?t=2044251
[MOD] True uncompressed MMS. CONFIRMED working!
I dont think it would work with our phone
Sent from my SM-G900P using XDA Free mobile app
slickdealers said:
Great find! Where do I change to allow MMS over WiFi? Is that the messaging limit?
Found the setting, but it still is compressing the image
Sent from my SM-G900P using Tapatalk
Click to expand...
Click to collapse
Settings--> Message limits--> Set max pixels for height/width to 2976 and set maximum message size to 10000 kilobytes.
So after having the same complaint myself and even from people I send messages to I decided to make the switch and try this out.
Works great with only 2 complaints.
1) Lock screen no longer shows a message preview?
2) No theme/alt. color for messages.
I can deal with number 2 but I really am use to having the first option and used it a lot to just quickly turn on screen to read a message without wanting to respond etc.
Is it just me or is it indeed broken on S5 with third-party messengers?
I'm actually happy with the stock one if it had a darn option to set mms sizes.
My old HTC use to have 500KB or 1MB, this thing has neither and it's keeping all my images under 350K it seems like.
All providers support 1024KB, it's stupid they compress them so much. AT&T was 600KB but I just sent myself a 1.2MB message and got it fine even oddly.
I just want 1MB without scaling bahh.
bryanu said:
So after having the same complaint myself and even from people I send messages to I decided to make the switch and try this out.
1) Lock screen no longer shows a message preview?
Click to expand...
Click to collapse
Download NiLS from Play Store. Damn amazing app!
I think I found a fix for this (maybe). If you decompile SecMms_Blue.apk and look @ the mms_config.xml these lines are there (stock)
Code:
<int name="maxMessageSize">307200</int>
<int name="mmsHeaderSize">5120</int>
<int name="maxImageHeight">480</int>
<int name="maxImageWidth">640</int>
Maybe increasing the values would result in less compression?
---------- Post added at 10:31 PM ---------- Previous post was at 10:01 PM ----------
fergie716 said:
I think I found a fix for this (maybe). If you decompile SecMms_Blue.apk and look @ the mms_config.xml these lines are there (stock)
Code:
<int name="maxMessageSize">307200</int>
<int name="mmsHeaderSize">5120</int>
<int name="maxImageHeight">480</int>
<int name="maxImageWidth">640</int>
Maybe increasing the values would result in less compression?
Click to expand...
Click to collapse
I made an apk and tried this, didn't work. Did unlock a few settings I found in that xml though
EDIT AGAIN
- I found this line in the customer.xml in csc/SPR/system/csc
Code:
<MessageSize>1m</MessageSize>
<ImageResizeResolution>uxga</ImageResizeResolution>
Ill see if editing this, along with the mms_config edits add up to anything
fergie716 said:
I think I found a fix for this (maybe). If you decompile SecMms_Blue.apk and look @ the mms_config.xml these lines are there (stock)
Code:
<int name="maxMessageSize">307200</int>
<int name="mmsHeaderSize">5120</int>
<int name="maxImageHeight">480</int>
<int name="maxImageWidth">640</int>
Maybe increasing the values would result in less compression?
---------- Post added at 10:31 PM ---------- Previous post was at 10:01 PM ----------
I made an apk and tried this, didn't work. Did unlock a few settings I found in that xml though
EDIT AGAIN
- I found this line in the customer.xml in csc/SPR/system/csc
Code:
<MessageSize>1m</MessageSize>
<ImageResizeResolution>uxga</ImageResizeResolution>
Ill see if editing this, along with the mms_config edits add up to anything
Click to expand...
Click to collapse
Odd, those first things you found are what I would expect to be the issue.
When you changed them and tested I take it you rebooted and tested it with a different MMS image?
I noticed if I send an MMS and go to send the same one again it seems to re-use the compressed version it made the first time, maybe try testing again with a different image to make sure?
Hopefully someone figures it out. I actually don't mind the stock app beyond this annoyance.
Thanks for looking/trying though.
bryanu said:
Odd, those first things you found are what I would expect to be the issue.
When you changed them and tested I take it you rebooted and tested it with a different MMS image?
I noticed if I send an MMS and go to send the same one again it seems to re-use the compressed version it made the first time, maybe try testing again with a different image to make sure?
Hopefully someone figures it out. I actually don't mind the stock app beyond this annoyance.
Thanks for looking/trying though.
Click to expand...
Click to collapse
I've tried multiple things including some smali edits but I'm on stock odex. If you're on a deodexed system upload your SecMms_Blue.apk from /system/priv-app/ and I'll make the same edits for you to see if they stick
I also decompiled the messaging app and made some changes like upping the max size to 2mb (2097152 bytes) and the height and width the same as 2.4 mp. I sent myself a picture that was ~700 kb and the resolution was 2.4 mp and the app still scaled it way down to something like 1600 X 900 I also made the CSC edits in customer.xml.
in the past the edits that fixed this was in the ImageModel.smali
search for this line
# direct methods
.method static constructor <clinit>()V
in here is where the goods are
vinman12 said:
in the past the edits that fixed this was in the ImageModel.smali
search for this line
# direct methods
.method static constructor <clinit>()V
in here is where the goods are
Click to expand...
Click to collapse
Ok I found this line in ImageModel.smali. I know nothing about editing smali and I'm not sure what I'm looking for This is copied directly from Notepad++
# direct methods
.method static constructor <clinit>()V
.locals 2
const/high16 v0, 0x434b0000
invoke-static {v0}, Lcom/android/mms/util/UIUtils;->dp2Pixels(F)I
move-result v0
sput v0, Lcom/android/mms/model/ImageModel;->THUMBNAIL_BOUNDS_LIMIT:I
invoke-static {}, Lcom/android/mms/ui/MessageUtils;->getScreenHeight()I
move-result v0
invoke-static {}, Lcom/android/mms/ui/MessageUtils;->getScreenWidth()I
move-result v1
if-le v0, v1, :cond_0
invoke-static {}, Lcom/android/mms/ui/MessageUtils;->getScreenWidth()I
move-result v0
mul-int/lit8 v0, v0, 0x2
:goto_0
sput v0, Lcom/android/mms/model/ImageModel;->SLIDESHOW_BOUNDS_LIMIT:I
invoke-static {}, Lcom/android/mms/MmsApp;->getApplication()Lcom/android/mms/MmsApp;
move-result-object v0
invoke-virtual {v0}, Landroid/content/ContextWrapper;->getResources()Landroid/content/res/Resources;
move-result-object v0
const v1, 0x7f0a004b
invoke-virtual {v0, v1}, Landroid/content/res/Resources;->getDimension(I)F
move-result v0
float-to-int v0, v0
sput v0, Lcom/android/mms/model/ImageModel;->THUMBNAIL_MAX_SHORT:I
invoke-static {}, Lcom/android/mms/MmsApp;->getApplication()Lcom/android/mms/MmsApp;
move-result-object v0
invoke-virtual {v0}, Landroid/content/ContextWrapper;->getResources()Landroid/content/res/Resources;
move-result-object v0
const v1, 0x7f0a004c
invoke-virtual {v0, v1}, Landroid/content/res/Resources;->getDimension(I)F
move-result v0
float-to-int v0, v0
sput v0, Lcom/android/mms/model/ImageModel;->THUMBNAIL_MAX_LONG:I
return-void
:cond_0
invoke-static {}, Lcom/android/mms/ui/MessageUtils;->getScreenHeight()I
move-result v0
mul-int/lit8 v0, v0, 0x2
goto :goto_0
.end method
Any progress update? 8sms is still compressing the images like the stock messaging app.
Ditto - can someone most a modded SecMMS_Blue.APK for NE5 ?
Would like to get the max MMS size bumped up to 5 or 10 MB
From browsing Sprint forums - sending MMS to Sprint phones has no limit max but most other carriers have a 1-2mb limit for MMS
I tried decompiling and editing, couldn't get it to work
tried decompressing and editing, then re-compressing the apk - apk kept force-closing
I'm probably missing something basic but can't figure out what it is.
Does_It_Matter said:
Ditto - can someone most a modded SecMMS_Blue.APK for NE5 ?
Would like to get the max MMS size bumped up to 5 or 10 MB
From browsing Sprint forums - sending MMS to Sprint phones has no limit max but most other carriers have a 1-2mb limit for MMS
I tried decompiling and editing, couldn't get it to work
tried decompressing and editing, then re-compressing the apk - apk kept force-closing
I'm probably missing something basic but can't figure out what it is.
Click to expand...
Click to collapse
Did you zipalign the apk ? Sac23 posted a modded SecMms_Blue in the MOAR thread.
Introduction (skip it if you are in a hurry )
Is it newer always better than older? not always indeed...
For example, the transition from Windows XP to Windows Vista, or from Windows 7 to 8 is been for many a move backward in terms of user experience and performance.
I would say that also the new *security* features inplemented starting with Android KitKat, that highly limited the usage of the external physical SDcard and introduced a quite confusing virtual/emulated internal SDcard, gave to many users who switched to the newer Android OS a number of problems and limitations they didn't have before.
Beside operative systems, also on the applications world, of course, sometimes an older app is better than a newer.
I, for example, can't get used to the new Messaging app look, that I found on my new phone, once I for years happily and comfortably used the Messaging app that was available on my *old* Samsung Galaxy Y (with Android GingerBread 2.3.6) which was optimized for a small screen and therefore very essential but still complete and able to provide a good user experience.
Some of us, smartphone users, would like that switching to a bigger screen phone from a smaller one, would give us the chance to have bigger text, menus, labels, so that everything can be read easier than on previous smaller phone...
But that doesn't seem what developers (who are eventually very young and so their sight is still very good ) usually think when they have a chance to deal with a bigger screen... they rather think that a bigger screen should give the opportunity to display more things, than the same things as previously but bigger.
So, moving from my old and beloved Samsung Galaxy Y, 3inch screen, to a new Cloudfone (asian brand) 4inch smartphone didn't make me any easier to read the texts on the screen, but instead I found the screen filled of new "things" and even "empty spaces" that honestly I don't really feel the need and I found very questionable their presence... (I think that sometimes developers are just like some journalists that are in need of a "scoop", and that if they don't have one, they will try to make it out of a normal news... the marketing department usually pressure the developers to "invent" new things, a "different look" whatever it is, so that they can sell it to the public as "new"... because... you know... new is better. So it doesn't matter if "new" is really "useful", as it doesn't matter if a "scoop" is really "real").
So I tried to find an alternative SMS app on Google Play store, that looked as close as possible like my old Messaging app.
I didn't find any that looked as I wanted by default, but I found that "chomp SMS" was very customizable, featuring many "theme" options (I especially liked the option to remove the contact pics, which most of the time are just a useless box with the contact initials) that made it possible to have it looked similar, even though not same, to my previous SMS app.
Yet, the waste of screen space for empty areas, and the formats of date and time labels and other details made me willing to use my reverse engineering skills to modify "chomp SMS" so that it looks perfectly same as the SMS app I was using before.
Here below I'll show you what I've done, what I modified and where, so that you too can do your modifications at your will, if you like to.
Let's start!
This is how the default Messaging app on both the phones, the old smaller, and the bigger new, looks like.
"Conversation List" view (first pic) and "Conversation" view (second pic)
.
I then found, on Google Play Store, and installed "chomp SMS", which by default looks like this.
.
I then went into Settings and used all the available options to customize the app look and this is the best that I've been able to achieve.
.
Compare the above with this screenshots of the SGY original Messaging app that we'll use as reference
.
From now on the only thing to do is to modify the app resources and code so...
first of all, you need to know how to decompile, compile and sign an Android app package.
If you don't know how, the simplest way to do it is to use APK Studio, a nice IDE (Integrated Development Environment) application, running on Windows and Linux, made by XDA developers member vaibhavpandeyvpz
Read this http://www.xda-developers.com/decompile-edit-and-recompile-in-one-tool-with-apk-studio/
Unfortunately such software might not work due to an older embedded version of APK Tool.
So, well... you might want to use the below attacched zip file that contains my own batch files together with the latest version of APK Tool (v2.1.0) that I downloaded from here http://ibotpeaches.github.io/Apktool/install/
Just download the zip and expand the archive in your C: disk.
You need to have at least Java Runtime Environment (JRE) ver. 1.8.0 installed (http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html)
Simply copy the apk file to that C:/Decompression.chamber folder and drag it over the apktool_decomp batch file and release, to get the apk decompiled.
As result you'll have a new folder in C:/Decompression.chamber with the same name of the decompiled apk.
To compile and sign just drag the folder over the apkt_BuildNsign batch file and release... if everything will be fine you'll find a new file named out.apk inside C:/Decompression.chamber and that's the compiled and signed apk.
Now, get the chomp SMS apk file and decompile it. (can be downloaded from here http://www.apk4fun.com/apk/1180/)
Now you are ready to modify the app same as I did (or on your own different way )
1) Let's get rid of that waste of screen space...
at the sides of the message box bubbles in Conversation view.
.
Looking on the layout folder (C:\Decompression.chamber\com.p1.chompsms-1\res\layout) we can find a file name message.xml that contains the description of the elements that are visualized on the Conversation view (how I found it? I don't remember I guess I just spot it by reading all the names of the files in the layout folder)
The message.xml file begins with this row:
Code:
<?xml version="1.0" encoding="utf-8"?>
<com.p1.chompsms.views.Message a:orientation="vertical" a:paddingLeft="2.0dip" a:padding ...
We can understand then that the contents of this layout is dynamically controller by a piece of code (a "class"), of name com.p1.chompsms.views.Message, that we can read by opening the related smali file, of name Message.smali, that we can find in (C:\Decompression.chamber\com.p1.chompsms-1\smali)\com\p1\chompsms\views.
By looking inside Message.smali we can find a few rows of code like this:
Code:
invoke-virtual {v2, v1, v3, v4, v5}, Landroid/widget/RelativeLayout$LayoutParams;->setMargins(IIII)V
Those rows, obviously, will set the message layout margins, that means the outer distance from the message box and the "container" the screen borders.
Few lines of code above, you can find a couple of "const"ants, means "fixed values"
Those constants are set by this code instructions
Code:
const/high16 v3, 0x428c0000 # 70.0f
That means that the value stored on "v3" is equal to 70.0 (floating point number).
Actually 70.0dpi is exactly the big "margin" that we want to remove.
There's also another margin, on the opposite side, which is much smaller (but still a waste) and it's set to only 2.0dpi by instructions const/high16 v1, 0x40000000.
In order to remove those margins we need to set to zero those constants by searching and replacing all the occurrences of 0x428c0000 and 0x4000000 with 0x00000000
If you wonder how can be 0x428c0000 equal to 70.0 give a look to this useful webpage http://www.h-schmidt.net/FloatConverter/IEEE754.html
Here's the result of this first modification.
(first pic is "before", second is "after")
.
.
2) Let's put the timestamp inside the message box bubble
The timestamp position is defined inside the message.xml layout file (already mentioned above) located in C:\Decompression.chamber\com.p1.chompsms-1\res\layout.
Having a look to that file we can see a reference to the timestamp at row number 4, above everything else, and identified by the attribute a:id="@id/message_date_label"
Code:
<TextView a:textAppearance="?historyDateTextAppearance" a:layout_gravity="center_horizontal" a:id="@id/message_date_label" a:paddingLeft=...
In order to have it inside and at the bottom of the message box, we have to move that line down, exactly under the line identified by the label a:id="@id/message_field" so that this:
Code:
<com.p1.chompsms.views.LinearLayoutWithOverlay a:layout_gravity="bottom" a:orientation="vertical" a:id="@id/message_view" ....
<TextView a:textAppearance="?historyMessageTextAppearance" a:autoLink="phone|email|web" a:id="@id/message_field" ...
<ViewStub a:layout_gravity="center_horizontal" a:id="@id/mms_layout_view_stub" ...
</com.p1.chompsms.views.LinearLayoutWithOverlay>
become this:
Code:
<com.p1.chompsms.views.LinearLayoutWithOverlay a:layout_gravity="bottom" a:orientation="vertical" a:id="@id/message_view" ...
<TextView a:textAppearance="?historyMessageTextAppearance" a:autoLink="phone|email|web" a:id="@id/message_field" ...
<TextView a:textAppearance="?historyDateTextAppearance" a:layout_gravity="right" a:id="@id/message_date_label" ...
<ViewStub a:layout_gravity="center_horizontal" a:id="@id/mms_layout_view_stub" ...
</com.p1.chompsms.views.LinearLayoutWithOverlay>
As in the original layout the timestamp is set to be positioned on the center of the screen, we also need to change the a:layout_gravity attribute from "center_horizontal" to "right" so that it will be positioned at the bottom/right of the message text.
Here's the result of the second modification (I changed the timestamp color to black using the app theme settings)
.
3) Let's change the timestamp date and time format
In my opinion the timestamp format that chomp SMS developer had chosen is unnecessarily too long and a not immediately clear as in the Messaging app of the SGY.
Unfortunately find where in the app is defined the date and time format of the timestamp isn't that easy because the chomp SMS developer(s) didn't link the format to any "style" or attr or string or anything that can be found in the "values" folder within the "res" (resources) folder; instead the format is "set" in the programmig code, somewhere, in one of the 4143 smali files
Anyway the code must be "called" by Message.smali (mentioned above) somewhere as that's the part of the app that handle the contents of the Conversation view, including the timestamp.
By searching for the id message_date_label (which refers to the timestamp textview inside message.xml layout) inside Message.smali and for "date" I then found the method setDate(J)V
Code:
.method public setDate(J)V
.locals 3
.prologue
.line 264
iget-object v0, p0, Lcom/p1/chompsms/views/Message;->m:Landroid/widget/TextView;
new-instance v1, Ljava/util/Date;
invoke-direct {v1, p1, p2}, Ljava/util/Date;-><init>(J)V
iget-object v2, p0, Lcom/p1/chompsms/views/Message;->c:Landroid/content/Context;
invoke-static {v1, v2}, Lcom/p1/chompsms/util/cd;->b(Ljava/util/Date;Landroid/content/Context;)Ljava/lang/String;
move-result-object v1
invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
.line 265
return-void
.end method
Here we can see that "m", which earlier is been initialized as a pointer to the timestamp view, is read (iget-object) and stored in v0, then an object "date" and the object "c" are passed to a method "b" defined in com/p1/chompsms/util/cd that will return a "text" (stored in v1) that will be set (with setText) in v0, the timestamp view!
So we need to look at the code of (C:\Decompression.chamber\com.p1.chompsms-1\smali)\com\p1\chompsms\util\cd.smali.
In cd.smali, at the part of the code related to .method public static b(Ljava/util/Date;Landroid/content/Context called by setDate in Message.smali, we can find the instructions that are executed to "build" the timestamp string, with a space (const-string v1, " ") used as junction of the date and the time part of the timestamp text.... bingo!
So now we know that is inside cd.smali that the timestamp is "build"... but unfortunately the code there doesn't use any "string" to format the date and time but, instead, it just call/uses the standard format provided by the operative system
So things are getting more complicated.
In order to change the date and time format we actually need to add some "new" code in cd.smali that will set the format in the way we want.
Here is the code I've added.
In the beginning section # static fields I've added the following that define a couple of additional objetcs containers, "i" and "l" (l like lima)
Code:
.field private static final i:Ljava/text/SimpleDateFormat;
.field private static final l:Ljava/text/SimpleDateFormat;
More down after the marker .line 45 and the instruction
Code:
sput-object v0, Lcom/p1/chompsms/util/cd;->h:Ljava/text/SimpleDateFormat;
I've added the following that stores on "i" and "m" two different formats, one for the time and the other for the date
Code:
.line 99967
new-instance v0, Ljava/text/SimpleDateFormat;
const-string v1, "h:mma"
invoke-direct {v0, v1}, Ljava/text/SimpleDateFormat;-><init>(Ljava/lang/String;)V
sput-object v0, Lcom/p1/chompsms/util/cd;->i:Ljava/text/SimpleDateFormat;
new-instance v0, Ljava/text/SimpleDateFormat;
const-string v1, "d MMM"
invoke-direct {v0, v1}, Ljava/text/SimpleDateFormat;-><init>(Ljava/lang/String;)V
sput-object v0, Lcom/p1/chompsms/util/cd;->l:Ljava/text/SimpleDateFormat;
I then added the following code (which read the format from "i" and apply it to the date stored in p0) inside .method public static b(Ljava/util/Date;Landroid/content/Context
Code:
.line 999388
sget-object v1, Lcom/p1/chompsms/util/cd;->i:Ljava/text/SimpleDateFormat;
invoke-virtual {v1, p0}, Ljava/text/SimpleDateFormat;->format(Ljava/util/Date;)Ljava/lang/String;
move-result-object v1
.line 999395
which goes right above before this:
Code:
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
const-string v1, " "
then const-string v1, " " is been replaced with const-string v1, ", " (I added a comma)
More down, six lines down from const-string v1, ", " , soon after this
Code:
invoke-virtual {v1, p0}, Ljava/text/DateFormat;->format(Ljava/util/Date;)Ljava/lang/String;
move-result-object v1
I've added the following:
Code:
.line 999415
sget-object v1, Lcom/p1/chompsms/util/cd;->l:Ljava/text/SimpleDateFormat;
invoke-virtual {v1, p0}, Ljava/text/SimpleDateFormat;->format(Ljava/util/Date;)Ljava/lang/String;
move-result-object v1
.line 999422
And here is the result of all those modifications...
.
not bad ah?
4) Let's change the bubble style and make it same as in the SGY Messaging app
chomp SMS provides a number of different message box "bubble" styles but in my opinion non of them has the same nice proportions of corners radius and "tail" as seen in the SGY Messaging app.
The bubble styles are actually defined by some related images that are part of the app resources and are saved on (C:\Decompression.chamber\com.p1.chompsms-1\res)\drawable-????-v4, where ???? is anything like ldpi, mdpi, hdpi, etc...
What we need to do is to get the 9.patch (resizable) images from the SGY Messaging apk and save them in the chomp SMS resource folder with the same name of the images that are related to the chomp SMS bubble style that we want to replace
So, first we need to find the images on the SGY Messaging app.
We need to get the apk from an SGY stock firmware... actually the apk name isn't Messaging but Mms .apk. Once we have the apk we need to decompile it and look inside the res folder for any "drawable-????-v4" folder, then using the preview, scroll all the images till one that looks similar to the bubble style is found.
Here is what I've found in (C:\Decompression.chamber\Mms)\res\drawable-ldpi-v4
.
.
.
The images names are respectively: message_bubble_readmessage.9.png, message_bubble_readmessage_selected.9.png, message_bubble_sentmessage.9.png, message_bubble_sentmessage_selected.9.png
This images are very small, and indeed belong the "ldpi" drawable group, that is meant to be used on small screen devices; they can be used on phones with bigger screen too, but they will be scaled up and therefore the image will result blurred along the borders.
These are the images that I found that are related to one of the bubble styles available in chomp SMS and that I chose as the ones that will be replaced.
.
.
.
The images names are respectively,incoming_bubble_matte_retina.9.png, incoming_bubble_matte_retina_selected.9.png, outgoing_bubble_matte_retina.9.png, outgoing_bubble_matte_retina_selected.9.png
These images are available in both mdpi and hdpi versions so their "quality", their resolution is higher than the one available on the SGY Messaging app.
As we are going to copy the SGY Messaging app images in the (C:\Decompression.chamber\com.p1.chompsms-1)\res\drawable-ldpi-v4 folder of decompiled chomp SMS (it has to be the ldpi folder because is the one that match with the size of the images) but the chomp original images are in the mdpi and hdpi folders, we need to delete the original images so chomp SMS app is "forced" to get the images from the ldpi folder.
Then the images from the SGY Messaging app, once copied on the ldpi folder of chomp SMS, they need to be renamed with the same names of the original chomp SMS images, so that chomp SMS app can find them
Here is the final result of the images substitutions (bubble style selector, before and after)
.
Conversation view scaled to be comparable in real size with the screen of SGY
.
5) Let's fix padding and margins in Conversation view
As you might have observed on the above screenshot the relative position of the text inside the message box isn't optimal and anyway doesn't match at all with our reference, the SGY Messaging app.
Also the bubble round corners are clearly blurred due to the low resolution of the 9.patch (resizable) images taken from the SGY Messaging apk.
In order to fix this we need to adjust the 9.patch borders lines that "controls" the padding, the distance between the inside message text and the bubble image borders.
There's also need to make new, bigger size images so that a better quality "bubble" image can be displayed.
Additionally some paddings attributes related to the Conversation view, have to be adjusted.
So here is the old (the first on the left) and the *new* images.
.
.
.
.
.
.
As you might observe the fix of the padding has been done by changing the lenght of the bottom and right/vertical borders black lines (more on that can be read here https://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch )
The bigger size images had to be made from scratch (I used GIMP as image editing application) using the original small as a reference. The tricky part was to properly reproduce the transparency (alpha channel) and the shadow.
The bigger images have exactly double the size as the original small one.
According to the Android developers documentations, ldpi images size relative factor is 0.75, mdpi is 1.0 and hdpi is 1.5, so that means that hdpi is 2.0 times than ldpi. By doubling the original small ldpi size the obtained image is suitable to be saved on the hdpi resources folder (C:\Decompression.chamber\com.p1.chompsms-1)\res\drawable-hdpi-v4; if the device is mdpi it will just scale down (by 0.66 factor) the hdpi image, but scaling down is much better than scaling up as it doesn't blur the image.
As the original chomp SMS hdpi versions of the bubble images have been already deleted, saving the new version on that folder won't be a file replacement, but it would have been if we didn't previously deleted the orginal images.
Padding and margins of message box and Conversation layout is also controlled by some values stored in (C:\Decompression.chamber\com.p1.chompsms-1)\res\layout\styles.xml; specifically this:
Code:
<style name="conversation_messageBubbles">
<item name="android:paddingLeft">3.0dip</item>
<item name="android:paddingRight">3.0dip</item>
The value of 3.0 has to be changed to 0.0
Also on (C:\Decompression.chamber\com.p1.chompsms-1)\res\layout\message.xml (that has been modified already above)
Change the attributes values according to this:
On row
Code:
<com.p1.chompsms.views.Message a:orientation="vertical"...
change:
paddingLeft="2.0dip" to 0.0
paddingRight="2.0dip" to 0.0
paddingBottom="8.0dip" to 6.0
On row
Code:
<LinearLayout a:orientation="horizontal" a:id="@id/message_view_wrapper" ...
change:
layout_marginBottom="4.0dip" to 0.0
On row
Code:
<TextView a:textAppearance="?historyDateTextAppearance" a:layout_gravity="right" a:id="@id/message_date_label" ...
replace:
layout_marginBottom="4.0dip" with layout_marginTop="3.0dip"
Once again, here is the achieved result...
.
Above: Conversation view scaled to be comparable in real size with the screen of SGY
Below: Close up of message bubble, before and after
.
Very close to perfect... isn't it?
The tutorial will continue on the following post...
6) Let's customize the "action bar"
The contact number shown in the action bar below the contact name is so ridiculously small that it can't be easily read, especially because a sequence of number is less likely to be visually recognized than a word that have "patterns" that our brain can use to recognize it.
Unfortunately chomp SMS, among the many theme settings, doesn't provide any related to the action bar contents, apart from the color.
So, once again, we need to find out where, in the app resources or code, are saved the values that controls the action bar contents appearance.
Looking at the content of the layout folder we can find a file named conversation.xml that likely will contain the description of the layout of the Conversation view and possibily has a reference to the action bar.
Indeed we can find, at row 5, the following
Code:
<FrameLayout a:id="@id/conversation_header_holder" a:background="?fakeActionBarBackground"
Still in layout folder we can find another file that might be related, with name action_bar_holder.xml
here we see that the second row contains this attribute
Code:
layout_height="?initialActionbarHeight"
The question mark tell use that the value is saved in the styles.xml files which can be found in (C:\Decompression.chamber\com.p1.chompsms-1)\values
Opening styles.xml file and searching for "initialActionbarHeight" we'll find the following:
Code:
<item name="initialActionbarHeight">@dimen/actionbar_height</item>
That means that the value of initialActionbarHeight is saved in dimens.xml file that can be found in the same value folder as styles.xml is.
Opening dimens.xml and searching for actionbar_height we'll find this:
Code:
<dimen name="actionbar_height">48.0dip</dimen>
bingo!
So, let's make the action bar bigger... let's change 48.0 in 52.0
Searching for "actionbar" inside styles.xml we can find a number of styles and values but with some analysis and trial and error attempts you can realize that styles that has "convo_actionbar_customview" in their name are the ones relevant.
Among them the follow two are the one that we are looking for:
Code:
<style name="convo_actionbar_customview_title" parent="@style/ActionBarTitle">
<item name="android:ellipsize">end</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:maxLines">1</item>
Code:
<style name="convo_actionbar_customview_subtitle" parent="@style/ActionBarTitle">
<item name="android:textSize">12.0sp</item>
<item name="android:ellipsize">end</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:maxLines">1</item>
Here we can see that the subtitle (which actually is the contact phone number, while the title is the contact name) has a textSize of 12.0sp... to have it bigger we need to, well... you know what!
Let's change it to 16.0sp and set a bit of free space at the bottom, to have it more vertically centered on the action bar, by adding the following line to the style
Code:
<item name="android:paddingBottom">3.0dip</item>
The convo_actionbar_customview_title style doesn't define its own textSize value, so it will just use the one set on the "parent" stlye ActionBarTitle, which is 18.0dip
Code:
<style name="ActionBarTitle" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
<item name="android:textSize">18.0dip</item>
I tried to change it to 20.0dip but it turned out that the textSize changed only if the contact name was displayed alone without the phone number (without subtitle), but if the number is shown then the contact name text size was as small as the original.
Doing some more searches in the the styles.xml file I then found the following line that belong the definition of the DefaultTheme style.
Code:
<item name="convo_actionbar_customview_title_with_subtitle_textsize">@dimen/convo_actionbar_customview_title_with_subtitle_textsize</item>
That line tells us that the dimension of the phone number is saved in dimens.xml file (already mentioned above) and indeed there we can find this:
Code:
<dimen name="convo_actionbar_customview_title_with_subtitle_textsize">16.0dip</dimen>
By replacing the value of 16.0dip with 20.0dip, the contact name will become bigger and easier to read.
:highfive:
I've observed that there's a glitch on how the ellipsis (the shortening of a text with addition of the theree dots) is applied to the contact name... it's sometimes much shorter than the available space.
I found out that the glitch is fixed if the singleLine attribute is enabled.
So let's add the following line to the convo_actionbar_customview_title style.
Code:
<item name="android:singleLine">true</item>
As last thing I wanted to remove the call button on the action bar because it has appened more than once that while I had the phone on my pants pocket and the screen was unlocked (forgot to lock) then accidentally the call button was touched and a phone call initiated without me being aware of it.
To find where in the app is defined the visualization of the call button, I started with a search for word "call" inside all the files existing in the chomp SMS decompiled app folder (C:\Decompression.chamber\com.p1.chompsms-1)
I then found that the button icon image is saved as ic_call_icon.png both on xhdpi and and xxxhdpi drawable folders.
Searching for ic_call_icon text inside all the files, I found a layout name ic_call_icon_wrapper.xml that contain a reference to that image.
Searching for ic_call_icon_wrapper, I found a smali file, (C:\Decompression.chamber\com.p1.chompsms-1)\smali\com/p1/chompsms/activities/Conversation.smali that contain a reference to ic_call_icon_wrapper layout.
At line 8510 of Conversation.smali, inside .method public onCreateOptionsMenu(Landroid/view/Menu we can find
Code:
sget v2, Lcom/p1/chompsms/s$f;->ic_call_icon_wrapper:I
by analyzing the code a little above and below that row it's possible to spot the "section" that actually initialize the button and attach to it an "intent" the "action" to initiate a call.
To avoid the button to be displayed we can set a jump in the code that will make the execution to bypass that section.
So here it is how to add the jump:
After
Code:
.line 822
invoke-static {}, Lcom/p1/chompsms/util/Util;->g()Z
move-result v0
if-eqz v0, :cond_2
add
Code:
.line 9998500
goto :goto_9998531
Before
Code:
.line 830
const/16 v1, 0xd
add
Code:
:goto_9998531
And now... as usual... the final result!
.
Before... after
That's more than enough for what concern the Conversation view... mission accomplished!
7) Let's "fix" the "Conversation list", the "main" view, layout
Let's have again a look at the chomp SMS conversations and compare it to the SGY Messaging app.
.
First of all I don't understand why the date should be on the same line of the contact name thus shorting it, instead of being on the same line of the message preview as it is in the old SGY Messaging app.
Secondly... I don't like that date format! :silly:
So... let's fix it.
As usual the first thing to do is to find the layout file, or smali file that control the appearance of the conversation list view.
The first guess is the layout file main.xml in res\layout folder.
It indeed contains some references to a few parts of the view, but not in detail the parts that we are looking to modify, which are eventually described on another layout file.
Scrolling the files in layout folder another one seems very promising by its name: conversation_row.xml
Found! bingo!
in conversation_row.xml there' are clear references to the contact name, message row, and date
Here is the related lines
For contact name and date
Code:
<com.p1.chompsms.activities.search.SearchResultTextView a:id="@id/person_label" ...
<com.p1.chompsms.views.TextViewWithEllipsesFix a:id="@id/date_label"...
For message text
Code:
<com.p1.chompsms.activities.search.SearchResultTextView a:id="@id/subject_label"
The textview id attributes (id/person_label, id/subject_label, id/date_label) makes it very sure that those lines are the one that controls the positions of contact name, message text, and date.
So, in order to change the relative positions we just have to properly move those lines within the layout
Let's cut the date_label TextView line and paste it right below the subject_label TextView line, so that it looks like this
Code:
<LinearLayout a:orientation="horizontal" a:layout_width="fill_parent" a:layout_height="wrap_content">
<com.p1.chompsms.activities.search.SearchResultTextView a:id="@id/subject_label"...
<com.p1.chompsms.views.TextViewWithEllipsesFix a:id="@id/date_label" ...
<ImageView a:layout_gravity="bottom" a:id="@id/pinned_marker"...
That's enough to move the date from the above line with the contact name to the below line with the message text.
But we can see that in the same line of the date, now (actually at the right of the date) there's the placeholder for the image that is used to a conversation row as "pinned".
The three objects, message text, date and marker are listed in three rows one below the other, but they will actually be displayed on one horizontal row, one next the other, as the LinearLayout they belong is set as orientation="horizontal".
Is better to move the pinned marker on the same row of the contact name, so... cut and paste right below the person_label TextView line, so that it looks like this
Code:
<LinearLayout a:orientation="horizontal" a:layout_marginTop="-3.0dip" ...
<com.p1.chompsms.views.BaseLineImageView a:id="@id/unread_marker"...
<com.p1.chompsms.views.BaseLineImageView a:id="@id/no_notification"...
<com.p1.chompsms.activities.search.SearchResultTextView a:id="@id/person_label"...
<ImageView a:layout_gravity="bottom" a:id="@id/pinned_marker"...
Ok, that's done
Now the "hard" part... the modification of date formatting.
To find where in the 1672 smali files contained in (C:\Decompression.chamber\com.p1.chompsms-1)\smali\com\p1\chompsms is the piece of code that set the date format we can try to trace back the chain starting from the conversation_row.xml layout.
Here we see that the date TextView contents is "controlled" by com.p1.chompsms.views.TextViewWithEllipsesFix that can be found and read as a smali file of name TextViewWithEllipsesFix.smali saved in (C:\Decompression.chamber\com.p1.chompsms-1)\smali\com\p1\chompsms\views
Giving a look at the code of that smali file doesn't show anything related to the date format, so it means that there must be another place, another smali file, that does the date formatting and then pass the result to TextViewWithEllipsesFix; we need to find any smali file that has inside a call to TextViewWithEllipsesFix.
Unfortunately, there's not even one smali file that contains a reference to Lcom/p1/chompsms/views/TextViewWithEllipsesFix in order to pass some data to it or call any of its method.
Eventually the code we are looking for is in (C:\Decompression.chamber\com.p1.chompsms-1)\smali\com\p1\chompsms\views\ConversationRow.smali that is defined in conversation_row.xml layout as the root view, the main container.
By reading the contents of ConversationRow.smali, we can see that at the beginning is defined a variable "p" made to contain a date object
Code:
.field private p:Ljava/util/Date;
A few line below, inside the .method public constructor, the "date" , received by as argument p0, is saved in "p".
Code:
iput-object v0, p0, Lcom/p1/chompsms/views/ConversationRow;->p:Ljava/util/Date;
Searching for the string "->p:Ljava/util/Date" we can see that "p" is used only in the .method public final b(J)Ljava/util/Date;
The method "b(J)Ljava/util/Date" isn't called anywhere within ConversationRow.smali, so the parameters it receives and the results it returns must be related to some code in some other smali file.
Searching the whole chomp SMS smali folder for files containing the string "b(J)Ljava/util/Date" gave me as result two files:
com/p1/chompsms/activities/conversationlist/ConversationList$a.smali
com/p1/chompsms/activities/search/a.smali
In a.smali, in .method public final bindView, at row 171 there's the call to method "b(J)"
Code:
invoke-virtual {v3, v4, v5}, Lcom/p1/chompsms/views/ConversationRow;->b(J)Ljava/util/Date;
The result of the call, supposedly it's a date or time, is then saved to v4, then v5 and v9 are set to numeric value "1", then v0 is set equal to p2 (a parameter received by the bindView method) then v4, v0, v5, v9 are all used to make a call to method a(Ljava/util/Date;Landroid/content/Context;ZZ)Ljava/lang/String defined in com\p1\chompsms\util\cd.smali
Code:
invoke-static {v4, v0, v5, v9}, Lcom/p1/chompsms/util/cd;->a(Ljava/util/Date;Landroid/content/Context;ZZ)Ljava/lang/String;
util\cd.smali ?
But that's the same cd.smali that we had to modify earlier to change the format of time and date in the conversation message timestamp!
Let's have a look to method "a(Ljava/util/Date;Landroid/content..." in cd.smali
The method is quite long, but it's clear that is doing some kind of operations on the date that it has received when is been called by a.smali, which has received the date from method "b" in conversation_row.smali.
The "a" method calls the calendar
Code:
invoke-virtual {v2, v3}, Ljava/util/Calendar;->get(I)I
in order to know how many days are past from the given date and the present time.
It then choose if in place of a "text" containing a formatted date it has to return a string like "today" or "yesterday"
Code:
.line 78
:cond_1
sget v0, Lcom/p1/chompsms/s$l;->today:I
Code:
.line 82
sget v0, Lcom/p1/chompsms/s$l;->yesterday:I
But if it's not the case for "today" or "yesterday", but still the given date isn't past than more than three days, than the method code will format the date using the SimpleDateFormat stored in "a" variable!
Code:
sget-object v0, Lcom/p1/chompsms/util/cd;->a:Ljava/text/SimpleDateFormat;
invoke-virtual {v0, p0}, Ljava/text/SimpleDateFormat;->format(Ljava/util/Date;)Ljava/lang/String;
move-result-object v0
If we look at the very beginning of the cd.smali file we can see that the date format stored in "a" is in the form of "EEEE"
Code:
const-string v1, "EEEE"
invoke-direct {v0, v1}, Ljava/text/SimpleDateFormat;-><init>(Ljava/lang/String;)V
sput-object v0, Lcom/p1/chompsms/util/cd;->a:Ljava/text/SimpleDateFormat;
"EEEE" is the standard pattern letter that refers to the "day of the week" (for more info read here https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html) and as the "E" letters are four then the name will be in full, not abbreviated... like Sunday and Monday, instead of Sun, and Mon.
So if the date that has been received is same as the present date or is one day or two days old the result would be either "today", "yesterday" or the day of the week, but if it's older...
Code:
.line 89
:cond_4
invoke-static {p1}, Lcom/p1/chompsms/util/cd;->b(Landroid/content/Context;)Ljava/text/DateFormat;
The DateFormat returned by .method private static declared-synchronized b(Landroid/content/Context; )Ljava/text/DateFormat will be used.
Having a look to the contents of that method we can see that it retrieves the DateFormat by querying the System Settings
Code:
const-string v2, "date_format"
invoke-static {v0, v2}, Landroid/provider/Settings$System;->getString(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;
That means that the Date Format will change (synchronized) accordingly with the current System settings.
Well... that's enough! Tiring ah? :silly:
So, we found it! :highfive:
But we still have to fix it... well... that's quite simple once we know where to put our hands
Let's just add a SimpleDateFormat as we already did before for the message TimeStamp and insert the code to force the use of that format instead of the one returned by method "b"
At the beginning of the cd.smali file, # static fields section, add
Code:
.field private static final m:Ljava/text/SimpleDateFormat;
At the end of .method static constructor <clinit>()V, below the code added before, add the following
Code:
new-instance v0, Ljava/text/SimpleDateFormat;
const-string v1, "d MMM yy"
invoke-direct {v0, v1}, Ljava/text/SimpleDateFormat;-><init>(Ljava/lang/String;)V
sput-object v0, Lcom/p1/chompsms/util/cd;->m:Ljava/text/SimpleDateFormat;
(note that "d MMM yy", is a pattern for a date format like 9 Sep 16)
Then, as last step, replace this
Code:
.line 89
:cond_4
invoke-static {p1}, Lcom/p1/chompsms/util/cd;->b(Landroid/content/Context;)Ljava/text/DateFormat;
move-result-object v0
invoke-virtual {v0, p0}, Ljava/text/DateFormat;->format(Ljava/util/Date;)Ljava/lang/String;
move-result-object v0
with this:
Code:
.line 89
:cond_4
sget-object v0, Lcom/p1/chompsms/util/cd;->m:Ljava/text/SimpleDateFormat;
invoke-virtual {v0, p0}, Ljava/text/SimpleDateFormat;->format(Ljava/util/Date;)Ljava/lang/String;
move-result-object v0
Job done! Congratulations! :highfive:
So, let's see how it looks the result of this hard work
.
8) The last touch
If you observe the above pictures you'll find that the Conversation list layout isn't as compact as in SGY Messaging app; moreover the divider line, for some reason, doesn't go all the way from one side to the other of the screen, but has a sort of "margin" distance on its left side.
In order to fine tuning the layout we need to change a few values here and there and add a few too
In values\styles.xml, style "conversationlist_row_content",
change android: paddingLeft value from 8.0 to 0.0
change android: paddingTop value from 10.0 to 7.0
change android: paddingRight value from 16.0 to 6.0
change android: paddingBottom value from 10.0 to 8.0
Code:
<style name="conversationlist_row_content">
<item name="android:paddingLeft">0.0dip</item>
<item name="android:paddingTop">7.0dip</item>
<item name="android:paddingRight">6.0dip</item>
<item name="android:paddingBottom">8.0dip</item>
In values\styles.xml, style "conversationlist_row_personlabel",
change android: paddingRight value from 6.0 to 0.0
add android:lineSpacingExtra with value -2.0dip
Code:
<style name="conversationlist_row_personlabel">
<item name="android:paddingRight">0.0dip</item>
<item name="android:lineSpacingExtra">-2.0dip</item>
In values\styles.xml, style "conversationlist_row_datelabel",
add android: paddingLeft with value from 6.0
Code:
<style name="conversationlist_row_datelabel">
<item name="android:paddingLeft">6.0dip</item>
In values\styles.xml, style "conversationlist_row_subjectlabel",
add android:singleLine with value "true" (to fix the glitch on the ellipsizing)
Code:
<style name="conversationlist_row_subjectlabel">
<item name="android:singleLine">true</item>
About the divider...
I hoped I could find any layout file or style attribute somewhere that was related to that left margin that prevents the divider to fill the screen from one side to the other... I couldn't... there's not such thing.
Once again, same as for the case of the message box margin, the divider left margin is "hardcoded".
By searching "divider" within all the smali files existing in (C:\Decompression.chamber\com.p1.chompsms-1)\smali\com\p1\chompsms, there are 27 smali files found but one of them has name ConversationList.smali that seems promising.
The file is located in (C:\Decompression.chamber\com.p1.chompsms-1)\smali\com\p1\chompsms\activities\conversationlist
Indeed... it's the right file!
It invokes setDivider...
Code:
invoke-virtual {v1, v0}, Lcom/p1/chompsms/activities/conversationlist/ConversationListListView;->setDivider(Landroid/graphics/drawable/Drawable;)V
... and setDividerHeight
Code:
invoke-virtual {v0, v1}, Lcom/p1/chompsms/activities/conversationlist/ConversationListListView;->setDividerHeight(I)V
Unlike what we found on com/p1/chompsms/views/Message.smali, in ConversationList.smali can't be found any call to setMargins method; there's instead a call to the InsetDrawable class.
Code:
invoke-direct/range {v0 .. v5}, Landroid/graphics/drawable/InsetDrawable;-><init>(Landroid/graphics/drawable/Drawable;IIII)V
Changing this
Code:
.line 678
:cond_0
const/high16 v1, 0x41800000 # 16.0f
To this
Code:
.line 678
:cond_0
const/high16 v1, 0x00000000 # 0.0f
Will get rid of the divider "margin"
Changing this
Code:
.line 683
iget-object v0, p0, Lcom/p1/chompsms/activities/conversationlist/ConversationList;->h:Lcom/p1/chompsms/activities/conversationlist/ConversationListListView;
const/high16 v1, 0x3f800000 # 1.0f
To this
Code:
.line 683
iget-object v0, p0, Lcom/p1/chompsms/activities/conversationlist/ConversationList;->h:Lcom/p1/chompsms/activities/conversationlist/ConversationListListView;
const/high16 v1, 0x3fc00000 # 1.0f
Will increase the divider thickness from 1.0dip to 1.5dip
So, now... it's showtime! :fingers-crossed:
.
Cherry on the cake
If the phone is connected to the Internet, every three times that the user "enter" one of the SMS conversations, chomp SMS will display an advertisment that will pin on top of the Conversation list... like this
and it will stay there untill the ad gets touched.
The ads are displayed according to their dedicated layouts; there are two different layouts: one generic and one specific for Facebook ads.
The two layouts are defined by two xml files: conversation_list_native_ad_row.xml and conversation_list_native_ad_row_facebook.xml
By adding the attribute a:visibility="gone" to the layouts, the ads won't be visibile anymore (please don't ask "how"... find it out yourself)
As cherry on the cake I decided to make a new app icon for the modified chomp SMS app; an icon that is a mix of the SGY Messaging icon and the original chomp SMS one.
+
=
The icon is of hdpi size and it's available for download as attachment to this post.
That's all folks!
If you have enjoyed to follow the tutorial your click on the thanks button here below will be highly appreciated
Thanks for reading
Reserved
good job. yes, apps keep getting worse. i guess the focus is now on getting your credit card number or harvesting your contacts for marketing, not with the user.
ok - somewhat unrelated, but i trust you'll know... - where does chomp SMS keep its blacklist? i need an SMS app that has an import function, but barring that, i could manipulate the file manually if it's text or XML.
hi, I never used the blacklist function so I didn't even never bother to know where it's saved.
Anyway usually apps have two preferred places where to save their data, one is the databases folder inside the app dedicated folder in the /data partition, the others is the shared_prefs also inside the app dedicated folder in /data/data.
After a quick check I found out that the blacklist is saved in the chompSMS Preferences.xml file.
Unfortunately the list is encoded so the numbers in the list aren't visibile and the app doesn't recognize the numbers if they aren't properly encoded.
You are so spot on with your comments in the first post. I have been using my old LG F3 for so long and the SMS worked so great with layout etc etc... I got a BLU Vivo last year because I needed a bigger screen for GPS driving...
I have just been using the larger phone for driving with my job, via a hotspot on the LG... but time had come to make the newer BLU phone my main phone...
And it has been drudgery finding a replacement app for the new phone, just getting the look and feel to the old phone which was perfect (stock SMS) circa 2013.
Chomp was close... I stumbled upon this post and I am stoked to try your work.
I've never done apk mods.. lots of other coding.. and I am excited to dive in with your examples as my first learning experience with apk.
Doing the date mod in the bubble, and removing wasted space in the bubble, is most important to me.
I am going to try to add an Icon for the "templates" somewhere on the screen, because I use them a lot.
If successful I'll get back and post the info.
Thanks a bunch for your work. I'm stoked !
Rob