Hi there, I want to share this tutorial for implementing Swipe-to-Remove Notification feature found in CyanogenMod to stock ROM (Gingerbread or earlier ROM). Sure it will be available on ICS but for those who like to add one to their custom ROM here's how Currently i don't know to whom should i give credit to, if anybody knows please post below and i'll add the link for the original modder. Thanks to:
1. like-p for help showing me what files to be edited
2. LeoMar75 for some info on how to control Stub switch case
This mod is based on Sony Ericsson Xperia Ray, so take care when adding to another device, some code might be different though so no direct copy paste, please learn some of the line first.
PS: For Froyo mod, please follow Jason-EX here
Requirement:
1. decompiled Framework.jar with Baksmali manager
2. decompiled SystemUI.apk with APK Multi Tool
3. Some Basic understanding about editing xml file and smali code.
4. WinMerge or other comparison tool (to better editing and comparing with my sample file)
5. Backup the framework.jar and SystemUI.apk first!
Files to be edited:
in SystemUI.apk
in framework.jar:
UPDATE: This is the additional guide for other device when editing StatusBarService.smali. See here:
1. HTC based
2. Samsung based
Alright, let's mod one by one
1. Editing SystemUI.apk
1.1 Editing res/anim
We are registering anim object here, so swipe animation can be done.
Update: Mirko ddd (&shoman94 have pointed that out before but i have no idea where to change, sorry mate) have given me the tip to improve the gesture. read his post here Thanks mate, both of you!
1.2 Editing res/layout/status_bar_latest_event.xml
We are replacing LinearLayout object used in StatusBar with LatestItemContainer here, so notification can be removed. We handle the Styling first by editing this .xml first. Here are the steps:
1.3 Editing res/values/public.xml
This one is for registering anim file that we made on step 1.1 to be available publicly and to be recognized in .smali program. Here are the steps:
1.4 Adding smali/com/android/systemui/statusbar/LatestItemContainer$1.smali and smali/com/android/systemui/statusbar/LatestItemContainer.smali
This is the class of LatestItemContainer that will be used to handle the notification list instead of LatestItemView. Here are the steps:
1.5 Add smali/com/android/systemui/statusbar/StatusBarService$7.smali (or depends on your existing framework numbering, could be $8 or larger)
This is additional function for StatusBarService to handle onClearNotification function. Here are the steps:
1.6 Edit smali/com/android/systemui/statusbar/StatusBarService.smali
UPDATE: This is the additional guide for other device when editing StatusBarService.smali. See here:
1. Generic java readout
2. HTC based
3. Samsung based
This is the file that generate NotificationView. Please take care of the changes here more carefully because there might be some differences between vendors in this file. Here are the steps:
Please note:
2. Editing framework.jar
2.1 editing smali/com/android/internal/statusbar/IStatusBarService$Stub.smali
Here are the steps:
2.2 Editing smali/com/android/internal/statusbar/IStatusBarService$Stub$Proxy.smali
Here are the steps:
2.3 editing smali/com/android/internal/statusbar/IStatusBarService.smali
Insert this function code to the file. Here are the steps:
There you have it AFAIK, the files that you need to take care more than others are:
1. smali/com/android/systemui/statusbar/StatusBarService.smali
2. res/values/public.xml
The rest can be applied from the attachment below directly. Ok that's all, after you are done, compile both SystemUI.apk and Framework.jar.
How to Compile the right way?
1. SystemUI.apk ->
and apply on your phone.
Hope this helps you (programmer ofc, not end user ) to implement on your device.
G'day!
1. like-p for help showing me what files to be edited
2. LeoMar75 for some info on how to control Stub switch case
This mod is based on Sony Ericsson Xperia Ray, so take care when adding to another device, some code might be different though so no direct copy paste, please learn some of the line first.
PS: For Froyo mod, please follow Jason-EX here
Requirement:
1. decompiled Framework.jar with Baksmali manager
2. decompiled SystemUI.apk with APK Multi Tool
3. Some Basic understanding about editing xml file and smali code.
4. WinMerge or other comparison tool (to better editing and comparing with my sample file)
5. Backup the framework.jar and SystemUI.apk first!
Files to be edited:
in SystemUI.apk
- res/anim/
- res/layout/status_bar_latest_event.xml
- res/values/public.xml
- smali/com/android/systemui/statusbar/LatestItemContainer$1.smali
- smali/com/android/systemui/statusbar/LatestItemContainer.smali
- smali/com/android/systemui/statusbar/StatusBarService$7.smali (or depends on your numbering, could be $8 or larger)
- smali/com/android/systemui/statusbar/StatusBarService.smali
in framework.jar:
- smali/com/android/internal/statusbar/IStatusBarService$Stub$Proxy.smali
- smali/com/android/internal/statusbar/IStatusBarService$Stub.smali
- smali/com/android/internal/statusbar/IStatusBarService.smali
UPDATE: This is the additional guide for other device when editing StatusBarService.smali. See here:
1. HTC based
2. Samsung based
Alright, let's mod one by one
1. Editing SystemUI.apk
1.1 Editing res/anim
We are registering anim object here, so swipe animation can be done.
- Create folder anim (if not exists yet) inside /res folder
- Create 2 file named slide_out_left_basic.xml and slide_out_right_basic.xml inside res/anim folder
- for slide_out_left_basic.xml, edit the file and fill with this
Code:<?xml version="1.0" encoding="utf-8"?> <translate android:duration="@android:integer/config_mediumAnimTime" android:fromXDelta="0.0" android:toXDelta="-100.0%p" xmlns:android="http://schemas.android.com/apk/res/android" />
- for slide_out_right_basic.xml, edit the file and fill with this
Code:<?xml version="1.0" encoding="utf-8"?> <translate android:duration="@android:integer/config_mediumAnimTime" android:fromXDelta="0.0" android:toXDelta="100.0%p" xmlns:android="http://schemas.android.com/apk/res/android" />
- Save both
Update: Mirko ddd (&shoman94 have pointed that out before but i have no idea where to change, sorry mate) have given me the tip to improve the gesture. read his post here Thanks mate, both of you!
1.2 Editing res/layout/status_bar_latest_event.xml
We are replacing LinearLayout object used in StatusBar with LatestItemContainer here, so notification can be removed. We handle the Styling first by editing this .xml first. Here are the steps:
- Change the code from Original code to this (change the bold one)
Code:<?xml version="1.0" encoding="utf-8"?> <[B]com.android.systemui.statusbar.LatestItemContainer [/B]android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="65.0sp" xmlns:android="http://schemas.android.com/apk/res/android"> <com.android.systemui.statusbar.LatestItemView android:id="@id/content" android:background="@android:drawable/status_bar_item_background" android:paddingRight="6.0sp" android:focusable="true" android:clickable="true" android:layout_width="fill_parent" android:layout_height="64.0sp" android:shadowColor="#ff000000" android:shadowDx="0.0" android:shadowDy="1.0" android:shadowRadius="2.0" /> <View android:background="@drawable/divider_horizontal_light_opaque" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <[B]/com.android.systemui.statusbar.LatestItemContainer[/B]>
- Save
1.3 Editing res/values/public.xml
This one is for registering anim file that we made on step 1.1 to be available publicly and to be recognized in .smali program. Here are the steps:
- Recompile your apk after putting anim file into /res folder
- Decompile again the resulting apk
- Inside /res/values/public.xml, you'll found something like this:
Code:<resources> . . . [B] <public type="anim" name="slide_out_left_basic" id="0x7f0c0000" /> <public type="anim" name="slide_out_right_basic" id="0x7f0c0001" /> [/B] </resources> [*]Remember the ID for both anim lines. This will be applied again on the step 1.4
1.4 Adding smali/com/android/systemui/statusbar/LatestItemContainer$1.smali and smali/com/android/systemui/statusbar/LatestItemContainer.smali
This is the class of LatestItemContainer that will be used to handle the notification list instead of LatestItemView. Here are the steps:
- Please download from the attachment
- insert the files inside to mentioned folder above
- Inside LatestItemContainer$1.smali, there's an id that references the anim from step1.2. please edit it if you have different id for anim left or anim from previous step.
Code:.line 53 :cond_0 const/high16 v1, [B]0x7f0c[/B]
Code:.line 51 const v1, [B]0x7f0c0001[/B]
1.5 Add smali/com/android/systemui/statusbar/StatusBarService$7.smali (or depends on your existing framework numbering, could be $8 or larger)
This is additional function for StatusBarService to handle onClearNotification function. Here are the steps:
- Extract the StatusBarService$7.smali from attachment
- If StatusBarService$7.smali does not exist before, just place it inside, if not, skip this step.
- If StatusBarService$7.smali exists, Please rename the file to StatusBarService$8.smali (or whatever higher number that is unused) and rename all the line inside the file from
Code:
StatusBarService$7
Code:StatusBarService$8
1.6 Edit smali/com/android/systemui/statusbar/StatusBarService.smali
UPDATE: This is the additional guide for other device when editing StatusBarService.smali. See here:
1. Generic java readout
2. HTC based
3. Samsung based
This is the file that generate NotificationView. Please take care of the changes here more carefully because there might be some differences between vendors in this file. Here are the steps:
- Open StatusBarService.smali and find this function
Code:.method makeNotificationView(Lcom/android/internal/statusbar/StatusBarNotification;Landroid/view/ViewGroup;)[Landroid/view/View;
- Find this code in the makeNotificationView function body:
Code:invoke-virtual {v0, v1, v2, v3}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View; move-result-object v18 const v4, 0x7f0b0014 move-object/from16 v0, v18 move v1, v4 invoke-virtual {v0, v1}, Landroid/view/View;->findViewById(I)Landroid/view/View; move-result-object v10
- Insert the bold code below between the existing code:
Code:invoke-virtual {v0, v1, v2, v3}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View; move-result-object v18 [B] check-cast v18, Lcom/android/systemui/statusbar/LatestItemContainer; .line 516 .local v18, row:Lcom/android/systemui/statusbar/LatestItemContainer; move-object/from16 v0, v16 iget v0, v0, Landroid/app/Notification;->flags:I move v4, v0 and-int/lit8 v4, v4, 0x2 if-nez v4, :cond_swno move-object/from16 v0, v16 iget v0, v0, Landroid/app/Notification;->flags:I move v4, v0 and-int/lit8 v4, v4, 0x20 if-nez v4, :cond_swno new-instance v4, Lcom/android/systemui/statusbar/StatusBarService$7; move-object v0, v4 move-object/from16 v1, p0 move-object/from16 v2, p1 invoke-direct {v0, v1, v2}, Lcom/android/systemui/statusbar/StatusBarService$7;-><init>(Lcom/android/systemui/statusbar/StatusBarService;Lcom/android/internal/statusbar/StatusBarNotification;)V move-object/from16 v0, v18 move-object v1, v4 invoke-virtual {v0, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->setOnSwipeCallback(Ljava/lang/Runnable;)V .line 735 :cond_swno[/B] const v4, 0x7f0b0014 move-object/from16 v0, v18 move v1, v4 [B] invoke-virtual {v0, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->findViewById(I)Landroid/view/View;[/B] move-result-object v10
Code:StatusBarService$7
Code:StatusBarService$8
IMPORTANT LOGIC TO BE UNDERSTOOD: This step tells the function to:
1. cast the already made View Object to LatestItemContainer instead of using LatestView class.
2. Filter if the Notification is removable or not
3. the LatestItemContainer object (v18) is assigned with onSwipeCallback(new StatusBarService$7)
- Change the following (still on the same function body):
Code:move v1, v4 invoke-virtual {v0, v1}, Landroid/view/View;->setDrawingCacheEnabled(Z)V .line 542 const/4 v4, 0x3
Code:move v1, v4 [B] invoke-virtual {v0, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->setDrawingCacheEnabled(Z)V [/B] .line 542 const/4 v4, 0x3
Please note:
- StatusBarService.smali might be different between vendor, so please adapt with your .smali to implement the above coding.
2. Editing framework.jar
2.1 editing smali/com/android/internal/statusbar/IStatusBarService$Stub.smali
Here are the steps:
- Add this code on variable declaration part inside the file
Code:.field static final TRANSACTION_onClearAllNotifications:I = 0xb [B].field static final TRANSACTION_onNotificationClear:I = 0xc[/B] .field static final TRANSACTION_onNotificationClick:I = 0x9 .field static final TRANSACTION_onNotificationError:I = 0xa
- If the 0xc is already used on another static value, you must change it so it remains unique.
- Find this code:
Code:
.method public onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z .registers 14 .parameter "code" .parameter "data" .parameter "reply" .parameter "flags" .annotation system Ldalvik/annotation/Throws; value = { Landroid/os/RemoteException; } .end annotation .prologue .line 39 sparse-switch p1, :sswitch_data_124
Code:.method public onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z .registers 14 .parameter "code" .parameter "data" .parameter "reply" .parameter "flags" .annotation system Ldalvik/annotation/Throws; value = { Landroid/os/RemoteException; } .end annotation .prologue .line 39 [B]sparse-switch p1, :sswitch_data_13e[/B]
- Insert/replace this code (it is at the end of the file):
Code:.line 176 const/4 v0, 0x1 goto/16 :goto_7 .line 39 :sswitch_data_124 .sparse-switch 0x1 -> :sswitch_f 0x2 -> :sswitch_1c 0x3 -> :sswitch_29 0x4 -> :sswitch_42 0x5 -> :sswitch_5f 0x6 -> :sswitch_7b 0x7 -> :sswitch_8d 0x8 -> :sswitch_c7 0x9 -> :sswitch_d5 0xa -> :sswitch_ef 0xb -> :sswitch_116 0x5f4e5446 -> :sswitch_8 .end sparse-switch
Code:[B] .line 176 const/4 v0, 0x1 goto/16 :goto_7 .end local v1 #_arg0:Ljava/lang/String; .end local v2 #_arg1:Ljava/lang/String; .end local v3 #_arg2:I :sswitch_124 const-string v0, "com.android.internal.statusbar.IStatusBarService" invoke-virtual {p2, v0}, Landroid/os/Parcel;->enforceInterface(Ljava/lang/String;)V .line 177 invoke-virtual {p2}, Landroid/os/Parcel;->readString()Ljava/lang/String; move-result-object v1 .line 178 .restart local v1 #_arg0:Ljava/lang/String; invoke-virtual {p2}, Landroid/os/Parcel;->readString()Ljava/lang/String; move-result-object v2 .line 179 .restart local v2 #_arg1:Ljava/lang/String; invoke-virtual {p2}, Landroid/os/Parcel;->readInt()I move-result v3 .line 180 .restart local v3 #_arg2:I invoke-virtual {p0, v1, v2, v3}, Lcom/android/internal/statusbar/IStatusBarService$Stub;->onNotificationClear(Ljava/lang/String;Ljava/lang/String;I)V .line 181 invoke-virtual {p3}, Landroid/os/Parcel;->writeNoException()V .line 182 const/4 v0, 0x1 goto/16 :goto_7[/B] .line 39 :sswitch_data_13e .sparse-switch 0x1 -> :sswitch_f 0x2 -> :sswitch_1c 0x3 -> :sswitch_29 0x4 -> :sswitch_42 0x5 -> :sswitch_5f 0x6 -> :sswitch_7b 0x7 -> :sswitch_8d 0x8 -> :sswitch_c7 0x9 -> :sswitch_d5 0xa -> :sswitch_ef 0xb -> :sswitch_116 [B]0xc -> :sswitch_124[/B] 0x5f4e5446 -> :sswitch_8 .end sparse-switch
- it's important to note this
Code:[B]0xc -> :sswitch_124[/B]
2.2 Editing smali/com/android/internal/statusbar/IStatusBarService$Stub$Proxy.smali
Here are the steps:
- Insert these function code to the file:
Code:.method public onNotificationClear(Ljava/lang/String;Ljava/lang/String;I)V .registers 9 .parameter "pkg" .parameter "tag" .parameter "id" .annotation system Ldalvik/annotation/Throws; value = { Landroid/os/RemoteException; } .end annotation .prologue .line 359 invoke-static {}, Landroid/os/Parcel;->obtain()Landroid/os/Parcel; move-result-object v0 .line 360 .local v0, _data:Landroid/os/Parcel; invoke-static {}, Landroid/os/Parcel;->obtain()Landroid/os/Parcel; move-result-object v1 .line 362 .local v1, _reply:Landroid/os/Parcel; :try_start_8 const-string v2, "com.android.internal.statusbar.IStatusBarService" invoke-virtual {v0, v2}, Landroid/os/Parcel;->writeInterfaceToken(Ljava/lang/String;)V .line 363 invoke-virtual {v0, p1}, Landroid/os/Parcel;->writeString(Ljava/lang/String;)V .line 364 invoke-virtual {v0, p2}, Landroid/os/Parcel;->writeString(Ljava/lang/String;)V .line 365 invoke-virtual {v0, p3}, Landroid/os/Parcel;->writeInt(I)V .line 366 iget-object v2, p0, Lcom/android/internal/statusbar/IStatusBarService$Stub$Proxy;->mRemote:Landroid/os/IBinder; const/16 v3, 0xa const/4 v4, 0x0 invoke-interface {v2, v3, v0, v1, v4}, Landroid/os/IBinder;->transact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z .line 367 invoke-virtual {v1}, Landroid/os/Parcel;->readException()V :try_end_21 .catchall {:try_start_8 .. :try_end_21} :catchall_28 .line 370 invoke-virtual {v1}, Landroid/os/Parcel;->recycle()V .line 371 invoke-virtual {v0}, Landroid/os/Parcel;->recycle()V .line 373 return-void .line 370 :catchall_28 move-exception v2 invoke-virtual {v1}, Landroid/os/Parcel;->recycle()V .line 371 invoke-virtual {v0}, Landroid/os/Parcel;->recycle()V throw v2 .end method
- Please inspect the code for this part:
Code:[B]const/16 v3, 0xa[/B] const/4 v4, 0x0 invoke-interface {v2, v3, v0, v1, v4}, Landroid/os/IBinder;->transact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
in my phone actually the valid one is the TRANSACTION_onNotificationError (0xa) so if your NotificationError is not 0xa but 0xb for example, please change the bold one to 0xb - Save
2.3 editing smali/com/android/internal/statusbar/IStatusBarService.smali
Insert this function code to the file. Here are the steps:
- Insert these function code to the file:
Code:.method public abstract onNotificationClear(Ljava/lang/String;Ljava/lang/String;I)V .annotation system Ldalvik/annotation/Throws; value = { Landroid/os/RemoteException; } .end annotation .end method
- Save
There you have it AFAIK, the files that you need to take care more than others are:
1. smali/com/android/systemui/statusbar/StatusBarService.smali
2. res/values/public.xml
The rest can be applied from the attachment below directly. Ok that's all, after you are done, compile both SystemUI.apk and Framework.jar.
How to Compile the right way?
1. SystemUI.apk ->
- Compile with APK Multi Tool, press y and y twice with all the requested input,
- delete modified file from keep folder, and after that continue compiling.
- Copy from original APK the META-INF and AndroidManifest.xml to the unsignedSystemUI.apk
- rename unsignedSystemUI.apk to signedSystemUI.apk
- select Zipalign from APK Multi Tool to optimize apk.
- Rename to SystemUI.apk (move the original one just in case)
- Smali inside Baksmali Manager
- Replace classes.dex inside framework.jar with the generated one.
and apply on your phone.
Hope this helps you (programmer ofc, not end user ) to implement on your device.
G'day!
Attachments
Last edited: