[HOWTO]Implement Swipe to Remove Notification

Search This thread

kirito9

Inactive Recognized Contributor
Oct 30, 2013
3,127
1,367
Thanks for this guide man :D :D i tried this before but did not get through because i didn't follow instructions properly. But now it's working :D :D
 

RealWelder

Senior Member
Sep 17, 2014
690
294
Muncie, IN
Help.

For Samsung Galaxy phone (sample taken from Captivate by CarpeNoctem here, hopefully applicable to all Samsung phone), the procedure is a bit different from Sony Ericsson one, but the logic is still the same. I have created a .java reconstruction from the .smali for the MakeNotificationView.

The Code logic is like this:
Code:
method makeNotificationView(StatusBarNotification p1, ViewGroup p2){
	v12 = 1;	//constant for value true
	v11 = 0;
	v10 = 0;	//Constant for value false
	
	v2 = p1.notification;
        v8 = v2.contentView;
	
	if(v8 == 0){								//If no Content to be Viewed
		return 0;
	}
	else{
		v1 = (LayoutInflater)this.getSystemService("layout_inflater");	//Create Layoutnflater originated from System
		v9 = (View)v1.inflate(7f030008,p2,v11);				//Pull XML(id:7f030008) and translate to Layout
		v7 = (ViewGroup)v9.findViewById(7f0a002d);			//Find Child View(id:7f0a002d) and try to cast to ViewGroup
		v7.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);		//FOCUS_BLOCK_DESCENDANTS = 0x6 in the code

		v7.setOnFocusChangeListener(v7.mFocusChangeListener);		//Attach onFocusChangeListener
		v3 = v2.contentIntent;						//Get Content Intent to be processed as Click Event

		if(v3 != 0){							//If v3 is something
			v7.setOnClickListener(new StatusBarService$Launcher(this,v3,p1.pkg,p1.tag,p1.id));	//Assign Click Listener based on contentIntent
		}

		try{
			v2 = v8.apply(this,v7);					//v2 is a new children View generated by v7
			v1 = v10;						

			v1 = this.getResources();
			this->updateThemeForNotificationView(v1,v2);
			v7.addView(v2);
			v9->setDrawingCacheEnabled(v12);
	
			v1 = 3;
			v1 = new View[3];
			v1[0] = v9;
			v1[1] = v7;
			v1[2] = v2;
			return v1;
		}catch(RunTimeException e){					//If Error, Create Log and return 0;
			v1 = e;
			v2 = 0;	

			// this is :cond_2 in code
			v2 = new StringBuilder();
			v2.append(v3);
			v2.append('/0x');
			v3 = Integer.toHexString(p1.id);
			v2 = v2.append('v3');
	
			v3 = "StatusBarService";
			v4 = new StringBuilder();
			v5 = "couldn\'t inflate view for notification ";
			v4.append(v5);
			v2 = v4.append(v2);
			Slog.e(v3,v2,v1);
			return 0;			
		}
	}
}

So if in My Sony Ericsson code:
1. the Notification View Object that will be modded is stored as v18 (later changed as v0), in Samsung it's stored as v9.
2. The Notification object retrieved from inside StatusBarNotification parameter (p1) stored as v16, in Samsung it is stored as v2

And from what i see, you may have this logic added (the bold one)
Code:
                v9 = (View)v1.inflate(7f030008,p2,v11);				//Pull XML(id:7f030008) and translate to Layout
                [B]if((v4 && 2) && (v4 && 20)){
			v4 = new StatusBarService$7(this,p1);
			v9.setOnSwipeCallback(v4);
		} [/B]
		v7 = (ViewGroup)v9.findViewById(7f0a002d);			//Find Child View(id:7f0a002d) and try to cast to ViewGroup

or in the .smali language from the link given above (for Captivate Only! please adapt to yours if different):
Code:
    .line 624
    const v3, 0x7f030008

    invoke-virtual {v1, v3, p2, v11}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View;

    move-result-object v9

    .line 627
    const v1, 0x7f0a002d

    invoke-virtual {v9, v1}, Landroid/view/View;->findViewById(I)Landroid/view/View;

    move-object v0, v1

    check-cast v0, Landroid/view/ViewGroup;

    move-object v7, v0

changed to

Code:
    .line 624
    const v3, 0x7f030008

    invoke-virtual {v1, v3, p2, v11}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View;

    move-result-object v9

[B]
    check-cast v9, Lcom/android/systemui/statusbar/LatestItemContainer;

    .line 516
    .local v9, row:Lcom/android/systemui/statusbar/LatestItemContainer;
    move-object/from16 v0, v2

    iget v0, v0, Landroid/app/Notification;->flags:I

    move v4, v0

    and-int/lit8 v4, v4, 0x2

    if-nez v4, :cond_1

    move-object/from16 v0, v2

    iget v0, v0, Landroid/app/Notification;->flags:I

    move v4, v0

    and-int/lit8 v4, v4, 0x20

    if-nez v4, :cond_1

    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;->(Lcom/android/systemui/statusbar/StatusBarService;Lcom/android/internal/statusbar/StatusBarNotification;)V

    move-object/from16 v0, v9

    move-object v1, v4

    invoke-virtual {v0, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->setOnSwipeCallback(Ljava/lang/Runnable;)V

    .line 735
    :cond_1[/B]

    .line 627
    const v1, 0x7f0a002d

    [B]invoke-virtual {v9, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->findViewById(I)Landroid/view/View;[/B]

    move-object v0, v1

    check-cast v0, Landroid/view/ViewGroup;

    move-object v7, v0

Hope this helps, it's geeky but it's the only way to understand ;) And one more thing, don't forget all the steps after it (esp. directive location :) )

I know this is an old mod, but I am trying to implement this to Samsung Galaxy Proclaim. Any help would be much appreciated. I have attached the files. (already decompiled and zipped)
 

Attachments

  • framework-file.zip
    8.7 MB · Views: 8

Top Liked Posts

  • There are no posts matching your filters.
  • 154
    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
    1. res/anim/
    2. res/layout/status_bar_latest_event.xml
    3. res/values/public.xml
    4. smali/com/android/systemui/statusbar/LatestItemContainer$1.smali
    5. smali/com/android/systemui/statusbar/LatestItemContainer.smali
    6. smali/com/android/systemui/statusbar/StatusBarService$7.smali (or depends on your numbering, could be $8 or larger)
    7. smali/com/android/systemui/statusbar/StatusBarService.smali

    in framework.jar:
    1. smali/com/android/internal/statusbar/IStatusBarService$Stub$Proxy.smali
    2. smali/com/android/internal/statusbar/IStatusBarService$Stub.smali
    3. 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.
    1. Create folder anim (if not exists yet) inside /res folder
    2. Create 2 file named slide_out_left_basic.xml and slide_out_right_basic.xml inside res/anim folder
    3. 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" />
    4. 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" />
    5. 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:
    1. 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]>
    2. 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:
    1. Recompile your apk after putting anim file into /res folder
    2. Decompile again the resulting apk
    3. 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]
      and
      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:
    1. Extract the StatusBarService$7.smali from attachment
    2. If StatusBarService$7.smali does not exist before, just place it inside, if not, skip this step.
    3. 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
      to
      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:
    1. Open StatusBarService.smali and find this function
      Code:
      .method makeNotificationView(Lcom/android/internal/statusbar/StatusBarNotification;Landroid/view/ViewGroup;)[Landroid/view/View;
    2. 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
    3. 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
      Once again, change
      Code:
      StatusBarService$7
      to
      Code:
      StatusBarService$8
      line if you happened to have StatusBarService$8.smali as the result of renaming on the previous step.

      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)
    4. 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
      to
      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:
    1. 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
    2. If the 0xc is already used on another static value, you must change it so it remains unique.
    3. 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
      change to
      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]
    4. 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
      to
      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
    5. it's important to note this
      Code:
      [B]0xc -> :sswitch_124[/B]
      If you rename the static at the previous steps, please change the 0xc accordingly.

    2.2 Editing smali/com/android/internal/statusbar/IStatusBarService$Stub$Proxy.smali
    Here are the steps:
    1. 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
    2. 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
      The bold one must match on one of the switch case value at the end of IStatusBarService$Stub.smali,
      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
    3. Save

    2.3 editing smali/com/android/internal/statusbar/IStatusBarService.smali
    Insert this function code to the file. Here are the steps:
    1. 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
    2. 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)
    2. framework.jar ->
    • 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 :rolleyes:) to implement on your device. :)

    G'day!
    26
    little "bug" resolved

    hi Hansip, I give you some good advice.

    I changed you animations left_out_basic.xml

    to:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <translate android:duration="@android:integer/config_mediumAnimTime" android:fromXDelta="0.0" android:toXDelta="-50.0%p"
      xmlns:android="http://schemas.android.com/apk/res/android" />

    and right_out_basic.xml

    to:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <translate android:duration="@android:integer/config_mediumAnimTime" android:fromXDelta="0.0" android:toXDelta="50.0%p"
      xmlns:android="http://schemas.android.com/apk/res/android" />

    this improves the swipe to remove act.
    Actually you have to swipe from the left edge to the right edge (or right to left) to remove notification, and this is annoying and often you have to be accureted in that action,now with my modification you can swipe less, even starting from center to left(right).
    I attach a pic to explain myself better
    24
    For Samsung Galaxy phone (sample taken from Captivate by CarpeNoctem here, hopefully applicable to all Samsung phone), the procedure is a bit different from Sony Ericsson one, but the logic is still the same. I have created a .java reconstruction from the .smali for the MakeNotificationView.

    The Code logic is like this:
    Code:
    method makeNotificationView(StatusBarNotification p1, ViewGroup p2){
    	v12 = 1;	//constant for value true
    	v11 = 0;
    	v10 = 0;	//Constant for value false
    	
    	v2 = p1.notification;
            v8 = v2.contentView;
    	
    	if(v8 == 0){								//If no Content to be Viewed
    		return 0;
    	}
    	else{
    		v1 = (LayoutInflater)this.getSystemService("layout_inflater");	//Create Layoutnflater originated from System
    		v9 = (View)v1.inflate(7f030008,p2,v11);				//Pull XML(id:7f030008) and translate to Layout
    		v7 = (ViewGroup)v9.findViewById(7f0a002d);			//Find Child View(id:7f0a002d) and try to cast to ViewGroup
    		v7.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);		//FOCUS_BLOCK_DESCENDANTS = 0x6 in the code
    
    		v7.setOnFocusChangeListener(v7.mFocusChangeListener);		//Attach onFocusChangeListener
    		v3 = v2.contentIntent;						//Get Content Intent to be processed as Click Event
    
    		if(v3 != 0){							//If v3 is something
    			v7.setOnClickListener(new StatusBarService$Launcher(this,v3,p1.pkg,p1.tag,p1.id));	//Assign Click Listener based on contentIntent
    		}
    
    		try{
    			v2 = v8.apply(this,v7);					//v2 is a new children View generated by v7
    			v1 = v10;						
    
    			v1 = this.getResources();
    			this->updateThemeForNotificationView(v1,v2);
    			v7.addView(v2);
    			v9->setDrawingCacheEnabled(v12);
    	
    			v1 = 3;
    			v1 = new View[3];
    			v1[0] = v9;
    			v1[1] = v7;
    			v1[2] = v2;
    			return v1;
    		}catch(RunTimeException e){					//If Error, Create Log and return 0;
    			v1 = e;
    			v2 = 0;	
    
    			// this is :cond_2 in code
    			v2 = new StringBuilder();
    			v2.append(v3);
    			v2.append('/0x');
    			v3 = Integer.toHexString(p1.id);
    			v2 = v2.append('v3');
    	
    			v3 = "StatusBarService";
    			v4 = new StringBuilder();
    			v5 = "couldn\'t inflate view for notification ";
    			v4.append(v5);
    			v2 = v4.append(v2);
    			Slog.e(v3,v2,v1);
    			return 0;			
    		}
    	}
    }

    So if in My Sony Ericsson code:
    1. the Notification View Object that will be modded is stored as v18 (later changed as v0), in Samsung it's stored as v9.
    2. The Notification object retrieved from inside StatusBarNotification parameter (p1) stored as v16, in Samsung it is stored as v2

    And from what i see, you may have this logic added (the bold one)
    Code:
                    v9 = (View)v1.inflate(7f030008,p2,v11);				//Pull XML(id:7f030008) and translate to Layout
                    [B]if((v4 && 2) && (v4 && 20)){
    			v4 = new StatusBarService$7(this,p1);
    			v9.setOnSwipeCallback(v4);
    		} [/B]
    		v7 = (ViewGroup)v9.findViewById(7f0a002d);			//Find Child View(id:7f0a002d) and try to cast to ViewGroup

    or in the .smali language from the link given above (for Captivate Only! please adapt to yours if different):
    Code:
        .line 624
        const v3, 0x7f030008
    
        invoke-virtual {v1, v3, p2, v11}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View;
    
        move-result-object v9
    
        .line 627
        const v1, 0x7f0a002d
    
        invoke-virtual {v9, v1}, Landroid/view/View;->findViewById(I)Landroid/view/View;
    
        move-object v0, v1
    
        check-cast v0, Landroid/view/ViewGroup;
    
        move-object v7, v0

    changed to

    Code:
        .line 624
        const v3, 0x7f030008
    
        invoke-virtual {v1, v3, p2, v11}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View;
    
        move-result-object v9
    
    [B]
        check-cast v9, Lcom/android/systemui/statusbar/LatestItemContainer;
    
        .line 516
        .local v9, row:Lcom/android/systemui/statusbar/LatestItemContainer;
        move-object/from16 v0, v2
    
        iget v0, v0, Landroid/app/Notification;->flags:I
    
        move v4, v0
    
        and-int/lit8 v4, v4, 0x2
    
        if-nez v4, :cond_1
    
        move-object/from16 v0, v2
    
        iget v0, v0, Landroid/app/Notification;->flags:I
    
        move v4, v0
    
        and-int/lit8 v4, v4, 0x20
    
        if-nez v4, :cond_1
    
        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;->(Lcom/android/systemui/statusbar/StatusBarService;Lcom/android/internal/statusbar/StatusBarNotification;)V
    
        move-object/from16 v0, v9
    
        move-object v1, v4
    
        invoke-virtual {v0, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->setOnSwipeCallback(Ljava/lang/Runnable;)V
    
        .line 735
        :cond_1[/B]
    
        .line 627
        const v1, 0x7f0a002d
    
        [B]invoke-virtual {v9, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->findViewById(I)Landroid/view/View;[/B]
    
        move-object v0, v1
    
        check-cast v0, Landroid/view/ViewGroup;
    
        move-object v7, v0

    Hope this helps, it's geeky but it's the only way to understand ;) And one more thing, don't forget all the steps after it (esp. directive location :) )
    10
    For Samsung the code above is almost right, there is a little mistake regarding this line:
    Code:
        move-object/from16 v2, p1

    In this way we are overwriting v2 but v2 is used later on on the same body function and it may results on FC. I advice to use a different variable, see the following code, i have used v7 because it was never set before.

    Code:
    .method makeNotificationView(Lcom/android/internal/statusbar/StatusBarNotification;Landroid/view/ViewGroup;)[Landroid/view/View;
        .locals 13
        .parameter
        .parameter
    
        .prologue
        const/4 v12, 0x1
    
        const/4 v11, 0x0
    
        const/4 v10, 0x0
    
        .line 642
        iget-object v2, p1, Lcom/android/internal/statusbar/StatusBarNotification;->notification:Landroid/app/Notification;
    
        .line 643
        iget-object v8, v2, Landroid/app/Notification;->contentView:Landroid/widget/RemoteViews;
    
        .line 644
        if-nez v8, :cond_0
    
        move-object v1, v10
    
        .line 682
        :goto_0
        return-object v1
    
        .line 649
        :cond_0
        const-string v1, "layout_inflater"
    
        invoke-virtual {p0, v1}, Lcom/android/systemui/statusbar/StatusBarService;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
    
        move-result-object v1
    
        check-cast v1, Landroid/view/LayoutInflater;
    
        .line 650
        const v3, 0x7f030009
    
        invoke-virtual {v1, v3, p2, v11}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View;
    
        move-result-object v9
    
        check-cast v9, Lcom/android/systemui/statusbar/LatestItemContainer;
    
        .local v9, row:Lcom/android/systemui/statusbar/LatestItemContainer;
        move-object/from16 v0, v2
    
        iget v0, v0, Landroid/app/Notification;->flags:I
    
        move v4, v0
    
        and-int/lit8 v4, v4, 0x2
    
        if-nez v4, :cond_leo
    
        move-object/from16 v0, v2
    
        iget v0, v0, Landroid/app/Notification;->flags:I
    
        move v4, v0
    
        and-int/lit8 v4, v4, 0x20
    
        if-nez v4, :cond_leo
    
        new-instance v4, Lcom/android/systemui/statusbar/StatusBarService$7;
    
        move-object v0, v4
    
        move-object/from16 v1, p0
    
        move-object/from16 v7, p1
    
        invoke-direct {v0, v1, v7}, Lcom/android/systemui/statusbar/StatusBarService$7;-><init>(Lcom/android/systemui/statusbar/StatusBarService;Lcom/android/internal/statusbar/StatusBarNotification;)V
    
        move-object/from16 v0, v9
    
        move-object v1, v4
    
        invoke-virtual {v0, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->setOnSwipeCallback(Ljava/lang/Runnable;)V
    
        :cond_leo		
        .line 653
        const v1, 0x7f0a0030
    
        invoke-virtual {v9, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->findViewById(I)Landroid/view/View;
    
        move-result-object v1

    Please note that i have named the label: cond_leo this is useful because in this way, we don't need to change other labels (cond_1,cond_2) on the rest of the body function!

    ;)
    7
    For HTC User (the code is from Dunc001) the logic is this:
    Code:
    method makeNotificationView(StatusBarNotification p1, ViewGroup p2){
    	v0 = p1;
    	v0 = v0.notification;
    	v23 = v0;
    	v0 = v23;
    	v24 = v0.contentView;
    
    	if(v24 == 0){
    		v4 = 0;
    		return v4;
    	}else{
    		v4 = 'layout_inflater';
    		v0 = this;
    		v1 = v4;
    		v22 = (LayoutInflater)v0->getSystemService(v1);
    		
    		v4 = 0x7f030012;
    		v5 = 0;
    		v0 = v22;
    		v1 = v4;
    		v2 = p2;
    		v3 = v5;
    		
    		v25 = v0->inflate(v1,v2,v3);
    
    		v4= 0x7f0a005f;
    		v0 = v25;
    		v1 = v4;
    		v16 = (ViewGroup)v0->findViewById(v1);
    		
    		v14 = 0;
    		v0 = v23;
    		v0 = v0->buttonAction;
    		v4 = v0;
    		if(v4 != 0){
    			v4 = 1;
    			v0 = v23;
    			v0 = v0->buttonAction;
    			v5 = v0;
    			v5 = v5->isEnable();
    			if(v4 == v5){
    				v0 = v16;
    				v0 = v0 instanceOf LatestItemView;
    				v4 = v0;
    				if(v4 != 0){
    					v14 = 1;
    				}
    			}
    		}
    		if(v14 != 0){			//:cond_1
    			v0 = (LatestItemView) v16;
    			v17 = v0;
    			v4 = 0;
    			v0 = v17;
    			v1 = v4;
    			v0->setDispatchTouchEvent(v1);
    			v4 = 2;
    			v0 = v16;
    			v1 = v4;	
    			v0->setDescendantFocusability(v1);
    		}else{
    			v4 = 6;
    			v0 = v16;
    			v1 = v4;
    			v0->setDescendantFocusability(v1);
    		}
    	
    		v4 = 6;
    		v0 = v16
    		v1 = v4;
    		v0->setDescendantFocusability(v1);	
    	
    		v0 = this;
    		v0 = v0->mFocusChangeListener;
    		v4 = v0;
    		v0 = v16;
    		v1 = v4;
    		v0->setOnFocusChangeListener();
    		
    		v0 = v23;
    		v0 = v0->flags;
    		v4 = v0;
    		v5 = fe;
    		
    		v4 = v4 AND v5;
    		if(v4 != 0){
    			v4 = -0xd6d3cf;
    			v0 = v16;
    			v1 = v4;
    			v0->setBackgroundColor();
    			p2 = (LinearLayout) v16->getParent();
    			v4 = 1;
    			v0 = p2;
    			v1 = v4;
    			v4 = v0->getChildAt();
    			v5 = 0x7f020044;
    			v4->setBackgroundResource(v5);
    		}	
    	
    		v0 = v0->contentIntent;
    		v6 = v0;	
    	
    		if(v6 != 0){
    			v0 = p1;
    			v0 = v0->pkg;
    			v7 = v0;
    			v0 = p1;
    			v0 = v0->tag;
    			v8 = v0;
    			v0 = p1;
    			v0 = v0->id;
    			v9 = v0;
    
    			v10 = 0;
    			v5 = p0;
    			v4 = new StatusBarService$Launcher(v5,v6,v7,v8,v9,v10);
    			v0 = v16;
    			v1 = v4;
    			v0->setOnClickListener(v1);
    		}
    
    		v19 = 0;
    		v18 = 0;
    		try{
    			v0 = v24;
    			v1 = p0;
    			v2 = v16;
    			v19 = v0->apply(v1,v2);
    		}catch(RuntimeException e){
    			e = v17;
    			v18 = v17;
    	
    		}
    		
    		
    		if(v19 == 0){
    			v4 = new StringBuilder();
    			v0 = p1;
    			v0 = v0->pkg;
    			v5 = v0;
    			v4 = v4->append(v5);
    			v5 = '/0x';
    			v4 = v4->append(v5);
    			v0 = p1;
    			v0 = v0->id;
    			v5 = v0;
    			v5 = Integer.toHexString(v5);
    			v4 = v4->append(v5);
    			v21 = v4->toString();
    			v4 = "StatusBarService";
    			v5 = new StringBuilder();
    			v6 = "couldn\'t inflate view for notification ";
    			v5 = v5->append(v6);
    			v0 = v5;
    			v1 = v21;
    			v5 = v0->append(v1);
    			v5 = v5->toString();
    			v0 = v4;
    			v1 = v5;
    			v2= v18;
    			SLog->e(v0,v1,v2);
    			v4 = 0;
    			return v4;
    		}
    
    		v0 = v16;
    		v1 = v19;
    		v0->addView();
    		v4 = 1;
    		v0 = v25;
    		v1 = v4;
    		v0->setDrawingCacheEnabled(v1);
    
    		if(v14 != 0){
    			v20 = 0;
    			do{
    				v4 = 3;
    				v0 = v20;
    				v1 = v4;
    				if(v0 <= v1){
    					v0 = v23;
    					v0 = v0->buttonAction;
    					v4 = v0;
    					v0 = v4;
    					v1 = v20;
    					v4 = v0->isEnable(v1);
    					if(v4 != 0){
    						v0 = v23;
    						v0 = v0->buttonAction;
    						v4 = v0;
    						v0 = v4;
    						v1 = v20;
    						v4 = v0->getViewId(v1);
    						v0 = v19;
    						v1 = v4;
    						v15 = v0->findViewById(v1);
    						if(v15 != 0){
    							v0 = v23;
    							v0 = v0->buttonAction;
    							v4 = v0;
    							v0 = v4;
    							v1 = v20;
    							v9 = v0->getPendingIntent(v1);
    							v0 = p1
    							v0 = v0->pkg;
    							v10 = v0;
    							v0 = p1;
    							v0 = v0->tag;
    							v11 = v0;
    							v0 = p1;
    							v0 = v0->id;
    							v12 = v0;		
    
    							v13 = 1;
    							v8 = p0;
    							v7 = new StatusBarService$Launcher(v7,v8,v9,v10,v11,v12,v13);
    
    							v15->setOnClickListener(v7);
    						}	
    					}	
    				}else break;
    				v20++;
    			}while(true);
    		}
    		
    		v4 = 3;
    		v4 = new View[3];
    		v4[0] = v25;
    		v4[1] = v16;
    		v4[2] = v19;
    		return v4;
    	}
    }

    so the difference is:
    1. We are focusing on v25 here as Notification Row Object
    2. Notification is stored as v23

    With that said, you can focus on inserting code around here
    Code:
        invoke-virtual {v0, v1, v2, v3}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View;
    
        move-result-object v25
    
        const v4, 0x7f0a005f
    
        move-object/from16 v0, v25
    
        move v1, v4
    
        invoke-virtual {v0, v1}, Landroid/view/View;->findViewById(I)Landroid/view/View;
    and change that to
    Code:
        invoke-virtual {v0, v1, v2, v3}, Landroid/view/LayoutInflater;->inflate(ILandroid/view/ViewGroup;Z)Landroid/view/View;
    
        move-result-object v25
    [B]
        check-cast v25, Lcom/android/systemui/statusbar/LatestItemContainer;
    
        .line 516
        .local v25, row:Lcom/android/systemui/statusbar/LatestItemContainer;
        move-object/from16 v6, v23
    
        iget v6, v6, Landroid/app/Notification;->flags:I
    
        move v7, v6
    
        and-int/lit8 v7, v7, 0x2
    
        if-nez v7, :cond_htc
    
        move-object/from16 v6, v23
    
        iget v6, v6, Landroid/app/Notification;->flags:I
    
        move v7, v6
    
        and-int/lit8 v7, v7, 0x20
    
        if-nez v7, :cond_htc
    
        new-instance v8, Lcom/android/systemui/statusbar/StatusBarService$7;
    
        move-object v7, v8
    
        move-object/from16 v8, p0
    
        move-object/from16 v9, p1
    
        invoke-direct {v7, v8, v9}, Lcom/android/systemui/statusbar/StatusBarService$7;->(Lcom/android/systemui/statusbar/StatusBarService;Lcom/android/internal/statusbar/StatusBarNotification;)V
    
        move-object/from16 v8, v25
    
        invoke-virtual {v8, v7}, Lcom/android/systemui/statusbar/LatestItemContainer;->setOnSwipeCallback(Ljava/lang/Runnable;)V
    
        .line 735
        :cond_htc[/B]
    
        const v4, 0x7f0a005f
    
        move-object/from16 v0, v25
    
        move v1, v4
    
        [B]invoke-virtual {v0, v1}, Lcom/android/systemui/statusbar/LatestItemContainer;->findViewById(I)Landroid/view/View;[/B]