TUT Hướng dẫn fix giao diện bàn phím gọi Tiếng Hàn (dialpad )

Thảo luận trong 'Dev Android' bắt đầu bởi hoangnova, 8 Tháng mười một 2013.

  1. hoangnova

    hoangnova Captain Staff Member

    Tham gia ngày:
    20 Tháng năm 2013
    Bài viết:
    6,738
    Đã được thích:
    15,889
    Fix bàn phím tiếng Hàn máy LG, bàn phím gọi tiếng Hàn, LGViet, hướng dẫn sửa bàn phím tiếng Hàn, bàn phím tiếng Hàn.

    Như đã biết ROM gốc của các dòng đt LG nội địa từ Hàn quốc, cái đầu tiên ta nhìn thấy là bàn phím gọi điện thoại toàn tiếng hàn, nhìn rất ghét.


    2.jpg

    Thông thường mọi người, chờ ai đó fix, rồi đưa file contact.apk đã sửa lên.

    Hôm nay mình sẽ dành một chút thời gian để viết một tut hướng dẫn các bạn hiểu đầu đuôi ngọn ngành của việc fix giao diện bàn phím tiếng Hàn, 1 việc tưởng chừng như đơn giản, nhưng không phải ai cũng biết. Đặc biệt là hiểu tường tận, ngọn nguồn của các fix để các bạn nắm đc, qua đó có thêm 1 chút kiến thức để xử lý các vấn đề tương tự.

    Với những người có nhiều kinh nghiệm kỹ năng thì việc này khá đơn giản, thậm chí mình còn ko cần nhìn code cũng có thể sửa đc.

    Các công cụ cần biết:

    - Dex2jar
    - Notepad++ + plugin smali để đọc code cho dễ
    - Apktool
    - java decompiler

    Fix bàn phím tiếng Hàn máy LG, bàn phím gọi tiếng Hàn, LGViet, hướng dẫn sửa bàn phím tiếng Hàn, bàn phím tiếng Hàn. Bài viết được thực hiện bởi hoangnova từ lgviet.com

    Các công cụ này mọi người tự search nhé, cách dùng thì có thể tìm lại các tút cũ mình đã viết để nắm đc, tránh mất thời gian lan man.

    Đầu tiên, dùng apktool, decompile file contactsbin.apk ra xem tình hình thế nào đã, luôn luôn là vậy, phải decompile ra xem trước xem làm gì với nó. Mở thử res/drawable-xhdpi xem có gì
    Ta thấy rằng các phím có tiếng hàn đó thực chất là 1 cái hình thôi.


    key_png.jpg

    Tới đây nếu lười ta ngồi đổi tên các hình cho nhau, sao cho nó mất tiếng Hàn và còn tiếng Anh thôi, thế thì dễ quá, nhưng mình thường làm cách sửa từ source để fix triệt để, tận gốc.

    Theo nhận định và kinh nghiệm thì thấy rằng nếu có cả tiếng anh và tiếng hàn thế kia thì hản là trong code nó check đâu đó để với quốc gia KR nó sẽ đổi thành bàn phím hàn, với ả rập nó sẽ ra bàn phím ả rập, với quốc gia khác nó sẽ ra bàn phím cuốc tế.

    Copy tên của 1 cái hình có tiếng hàn, ở đây mình thử copy phím số 2 có tiếng hàn có tên là "dial_num_2_wht__kr.png"

    Vào seảrch thử trong value để xem giá trị của nó

    3.jpg

    Có được cái id là mã hex rồi ta lại thử search tiếp thử trong code smali coi có gì ko. Thử cái nhé !
    Đây rồi, có luôn, vậy là mình đoán đúng:

    4.jpg


    Nó nằm trong class ResourceConfig

    Giờ ta cần dex2jar file classes.dex của Contact để xem code java nó viết gì nhé. Tất nhiên là thấy code rồi, nhưng làm sao để tìm thấy cái số kia ở trong code java ?!

    Ta cần đổi nó sang dạng số Decimal, bằng cách dùng calculator, làm như trong hình hướng dẫn dưới đây:

    5.jpg


    6.jpg

    Ta được dãy số 2130837710
    Ctrl + F để search thử xem sao.

    8.jpg

    Ta thấy nó nằm trong 1 method để gọi phím số 2 ra như sau:

    Mã:
      public int getDialNum2()
      {
        int i;
        if (SystemConfig.getCountry().equals(SystemConfig.COUNTRY.IL))
          i = 2130837709;
        while (true)
        {
          return checkedResourceId(i, 2130837708);
          if (SystemConfig.getCountry().equals(SystemConfig.COUNTRY.KR))
          {
            i = 2130837710;
            continue;
          }
          if (SystemConfig.getOperator().equals(SystemConfig.OPERATOR.TMUS))
          {
            i = 2130837711;
            continue;
          }
          i = 2130837708;
        }
      }
    Vậy là chắc chắn như mình nói, với nhà mạng Hàn quốc nó gọi ra 1 cái hình khác.

    Việc của ta làm gì bây giờ, tất nhiên cần biết 1 chút về code để quan sát và đọc hiểu code.

    Đoạn trên nó viết rằng SystemConfig.getCountry() = SystemConfig.COUNTRY.KR thì nó ra bàn phím số 2 bằng tiếng Hàn.

    Vậy ta thử lần theo SystemConfig.getCountry() để sửa nó thành 1 country khác xem sao nhé.

    trong class

    Mã:
      public static COUNTRY getCountry()
      {
        return mBuildCountry;
      }
    
    Nó viết, tức là trả về cái biến mBuildCountry, lần theo mBuildCountry nó viết

    mBuildCountry = getBuildCountry();

    còn thằng getBuildCountry thì đây

    Mã:
      private static COUNTRY getBuildCountry()
      {
        String str = SystemProperties.get("ro.build.target_country");
        Object localObject = COUNTRY.COM;
        try
        {
          COUNTRY localCOUNTRY = COUNTRY.valueOf(str);
          localObject = localCOUNTRY;
          Log.i("SystemConfig", "BUILD Country: " + localObject);
          return localObject;
        }
        catch (IllegalArgumentException localIllegalArgumentException)
        {
          while (true)
            Log.e("SystemConfig", "unknown country code=" + str);
        }
      }
    
    À, ra vậy, vậy là nó lấy cái country từ build.prop, vậy nếu ta sửa build.prop ro.build.target_country thì sao, thì cũng đc thôi, nhưng cái đó nằm ngoài phạm vi bài này, sẽ có 1 tút khác sau.
    Tiếp tục bài này:

    String str = SystemProperties.get("ro.build.target_country");

    Hay là thử gán nó bằng cái gì đó đại loại như ESA ( quốc tế) chẳng hạn:

    Sửa thế nào ? Xem code smali đã:

    Mã:
    .method private static getBuildCountry()Lcom/lge/contacts/util/SystemConfig$COUNTRY;
        .locals 6
     
        .prologue
        .line 580
        const-string v3, "ro.build.target_country"
     
        invoke-static {v3}, Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String;
     
        move-result-object v0
     
        .line 586
        .local v0, code:Ljava/lang/String;
        sget-object v1, Lcom/lge/contacts/util/SystemConfig$COUNTRY;->COM:Lcom/lge/contacts/util/SystemConfig$COUNTRY;
     
        .line 588
        .local v1, country:Lcom/lge/contacts/util/SystemConfig$COUNTRY;
        :try_start_0
        invoke-static {v0}, Lcom/lge/contacts/util/SystemConfig$COUNTRY;->valueOf(Ljava/lang/String;)Lcom/lge/contacts/util/SystemConfig$COUNTRY;
        :try_end_0
        .catch Ljava/lang/IllegalArgumentException; {:try_start_0 .. :try_end_0} :catch_0
     
        move-result-object v1
     
        .line 593
        :goto_0
        const-string v3, "SystemConfig"
     
        new-instance v4, Ljava/lang/StringBuilder;
     
        invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V
     
        const-string v5, "BUILD Country: "
     
        invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
     
        move-result-object v4
     
        invoke-virtual {v4, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     
        move-result-object v4
     
        invoke-virtual {v4}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
     
        move-result-object v4
     
        invoke-static {v3, v4}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
     
        .line 594
        return-object v1
     
        .line 589
        :catch_0
        move-exception v2
     
        .line 590
        .local v2, e:Ljava/lang/IllegalArgumentException;
        const-string v3, "SystemConfig"
     
        new-instance v4, Ljava/lang/StringBuilder;
     
        invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V
     
        const-string v5, "unknown country code="
     
        invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
     
        move-result-object v4
     
        invoke-virtual {v4, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
     
        move-result-object v4
     
        invoke-virtual {v4}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
     
        move-result-object v4
     
        invoke-static {v3, v4}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
     
        goto :goto_0
    .end method
    Chú ý đoạn này

    Mã:
        const-string v3, "ro.build.target_country"
     
        invoke-static {v3}, Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String;
     
        move-result-object v0
    Sẽ ra code java thành đoạn này:

    Mã:
    String str = SystemProperties.get("ro.build.target_country");
    Vậy gán mẹ cái v0 kia thành 1 string gì đó ta thích:

    Mình ko xóa code cũ đi mà đè cái v0 lên thành code thế này:

    Mã:
        const-string v3, "ro.build.target_country"
     
        invoke-static {v3}, Landroid/os/SystemProperties;->get(Ljava/lang/String;)Ljava/lang/String;
     
        move-result-object v0
     
        const-string v0, "EU"
    
    RỒi thử compile lại apk, và lại thử dex2jar lại ta sẽ thấy code java nó ra thế này:

    Mã:
      private static COUNTRY getBuildCountry()
      {
        SystemProperties.get("ro.build.target_country");
        Object localObject = COUNTRY.COM;
        try
        {
          COUNTRY localCOUNTRY = COUNTRY.valueOf("EU");
          localObject = localCOUNTRY;
          Log.i("SystemConfig", "BUILD Country: " + localObject);
          return localObject;
        }
        catch (IllegalArgumentException localIllegalArgumentException)
        {
          while (true)
            Log.e("SystemConfig", "unknown country code=" + "EU");
        }
      }
    Làm tương tự với thằng getBuildOperator()

    Sao cho cuối cùng nó ra code java thế này: Đoạn này nghĩa là ta gán getBuildOperator thành OPEN (cuốc tế) cho đồng bộ cùng Country.

    Mã:
     
      private static OPERATOR getBuildOperator()
      {
        SystemProperties.get("ro.build.target_operator");
        Object localObject = OPERATOR.OPEN;
        try
        {
          OPERATOR localOPERATOR = OPERATOR.valueOf("OPEN");
          localObject = localOPERATOR;
          if ((localObject == OPERATOR.TMO) && (isCountry(COUNTRY.US)))
            localObject = OPERATOR.TMUS;
          if ((localObject == OPERATOR.USC) && (isCountry(COUNTRY.MX)))
            localObject = OPERATOR.MXUSC;
          Log.i("SystemConfig", "BUILD Operator: " + localObject);
          return localObject;
        }
        catch (IllegalArgumentException localIllegalArgumentException)
        {
          while (true)
            Log.e("SystemConfig", "unknown operator code=" + "OPEN");
        }
      }
    
    Đến đây chỉ xong 1 phần thôi, còn 1 chỗ khác cần sửa để gán giá trị default:

    Ở trong: com/android/contacts/dialpad/DialpadFeature.smali
    Method .method public constructor <init>(Landroid/content/Context

    Thêm vào đoạn code :

    Mã:
            .line 253
        const/4 v2, 0x0
     
        sput v2, Lcom/android/contacts/dialpad/DialpadFeature;->mVTDevice:I
     
        sput-boolean v2, Lcom/android/contacts/dialpad/DialpadFeature;->isLGU:Z
     
        sput-boolean v2, Lcom/android/contacts/dialpad/DialpadFeature;->isKR:Z
     
        const/4 v2, 0x1
     
        sput-boolean v2, Lcom/android/contacts/dialpad/DialpadFeature;->isEU:Z
     
        .line 56
        const-string v2, "OPEN"
     
        sput-object v2, Lcom/android/contacts/dialpad/DialpadFeature;->OPERATOR:Ljava/lang/String;
     
        .line 56
        const-string v2, "EU"
     
        sput-object v2, Lcom/android/contacts/dialpad/DialpadFeature;->COUNTRY:Ljava/lang/String;
    
    Vào ngay bên dưới

    Mã:
        .line 253
        invoke-direct {p0}, Lcom/android/contacts/dialpad/DialpadFeature;->initVTDevice()V


    Sao cho khi ra code java nó thành thế này:
    Mã:
      public DialpadFeature(Context paramContext)
     
      {
     
        this.mContext = paramContext;
     
        this.mTelephony = ((TelephonyManager)paramContext.getSystemService("phone"));
     
        this.mAudioManager = ((AudioManager)paramContext.getSystemService("audio"));
     
        this.mCheckDeclaredClass = new CheckDeclaredClass("android.telephony.TelephonyManager");
     
        if (OPERATOR.equals(""))
     
        {
     
          Log.i(TAG, "OPERATOR : << UNKNOWN >>");
     
          OPERATOR = "OPEN";
     
        }
     
        if (COUNTRY.equals(""))
     
        {
     
          Log.i(TAG, "COUNTRY : << UNKNOWN >>");
     
          COUNTRY = "UNKNOWN";
     
        }
     
        Log.i(TAG, "OPERATOR : " + OPERATOR);
     
        Log.i(TAG, "COUNTRY : " + COUNTRY);
     
        Log.i(TAG, "MODEL_NAME : " + MODEL_NAME);
     
        initVTDevice();
     
        mVTDevice = 0;
     
        isLGU = false;
     
        isKR = false;
     
        isEU = true;
     
        OPERATOR = "OPEN";
     
        COUNTRY = "EU";
     
        Log.i(TAG, "VTDevice : " + mVTDevice);
     
        if (isLGU)
     
          initSupportLGUGlobalRoaming(paramContext);
     
        Log.i(TAG, "isLGUSupportGlobalRoaming : " + isLGUSupportGlobalRoaming);
     
      }
    Đoạn này nghĩa là gán đè toàn bộ những cái nó config trong DialpadFeature thành cái mình mong muốn, ở đây là

    Mã:
    mVTDevice = 0;
        isLGU = false;
        isKR = false;
        isEU = true;
        OPERATOR = "OPEN";
        COUNTRY = "EU";

    Hehe, xong rồi, compile lại và thay thế vào contact cũ, đảm bảo bây giờ mọi thứ thành cuốc tế hết. Xem kết quả đây (đẹp hơn bố của đẹp luôn)
    Download file đã sửa bàn phím tiếng Hàn cho LTE3 tại đây:
    Mình mod trên bản ROM của LTE3 mới nhất nhé: https://drive.google.com/file/d/0B3J7gOQH7ViEWUotRS1IYXpqT1E/edit?usp=sharing
    done.jpg


    dokyson: bàn phím tiếng Hàn LTE3
     
  2. Văn Chức

    Văn Chức Life Good

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    7,613
    Đã được thích:
    4,920
    Hay qué. Có cái này đỡ phải sửa hình anh ạ :D
    Hôm rồi HD 1 bạn mod cái thanh chỉnh sáng . Bạn ý kêu chóng mặt . Bây giờ mà xem cái này nữa là xỉu luôn. Kaka
     
    Xstt thích bài này.
  3. hoangnova

    hoangnova Captain Staff Member

    Tham gia ngày:
    20 Tháng năm 2013
    Bài viết:
    6,738
    Đã được thích:
    15,889
    Quan trọng nó sửa tận gốc, dùng thử bán phím gốc và bàn phím đã sửa này khác nhau nhiều thứ lắm đấy ;) cái đơn giản nhất là cách phân chia số khi mình gõ vào, ví dụ: 0933.888.333 gõ vào nó sẽ theo đúng chuẩn cuốc tế, ko phân chia kiểu Hàn Quốc.
     
    duonga4k6 thích bài này.
  4. Văn Chức

    Văn Chức Life Good

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    7,613
    Đã được thích:
    4,920
    Tối về e thực hành lun trên em Vú 2. Anh đang build cho LTE 3 ạ. Có cần tester kô a? :D
     
  5. hoangnova

    hoangnova Captain Staff Member

    Tham gia ngày:
    20 Tháng năm 2013
    Bài viết:
    6,738
    Đã được thích:
    15,889
    KO, a bận việc cty, chưa làm gì cả. Ko có nhiều htời gian.
     
  6. hoangnova

    hoangnova Captain Staff Member

    Tham gia ngày:
    20 Tháng năm 2013
    Bài viết:
    6,738
    Đã được thích:
    15,889
    Hiểu code java là điều cực kỳ quan trọng, đó là lý do mà ngay khi 4.1 cho LU ra a đã fix tất cả các lỗi chỉ trong vòng 24h đồng hồ ;)
     
  7. Văn Chức

    Văn Chức Life Good

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    7,613
    Đã được thích:
    4,920
    Chuẩn quốc tế là kô có dấu cách mà có chấm đúng kô a ?
     
  8. Văn Chức

    Văn Chức Life Good

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    7,613
    Đã được thích:
    4,920
    Anh có bận lâu kô ? 17 này e định ra đó tổ chức Off luôn :D cũng tính nhờ a chỉ bảo :D
     
  9. Đạt Nguyễn

    Đạt Nguyễn Vietnam's Gsm Team

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    1,112
    Đã được thích:
    1,445
    Trời thế anh đã bắt đầu xâm chiếm LTE3 rồi ạ
     
  10. Văn Chức

    Văn Chức Life Good

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    7,613
    Đã được thích:
    4,920
    E thì chỉ copy thui. Mấy cái xml dễ thì đc chứ code như smali khó quá .:D
     
  11. hoangnova

    hoangnova Captain Staff Member

    Tham gia ngày:
    20 Tháng năm 2013
    Bài viết:
    6,738
    Đã được thích:
    15,889
    A có nhiều máy mà, cầm con nào thì nghịch đại con ấy thôi, bài này a post vì đã hứa với dokyson thôi.
     
  12. Văn Chức

    Văn Chức Life Good

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    7,613
    Đã được thích:
    4,920
    A Hoàng muốn sở hữu tất cả smartphone Android LG mà :D
     
  13. hoangphucdt

    hoangphucdt Well-Known Member

    Tham gia ngày:
    11 Tháng tám 2013
    Bài viết:
    1,700
    Đã được thích:
    710
    Học 1 khóa lập trình mới hiểu được :(

    Gửi từ LG-F160 của tôi bằng cách sử dụng Tapatalk 2
     
  14. Đạt Nguyễn

    Đạt Nguyễn Vietnam's Gsm Team

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    1,112
    Đã được thích:
    1,445
    Đại ca ơi tối rảnh không nếu tối anh rảnh chỉ em 1 số thứ em còn thắc mắc được không ạ
     
  15. Đạt Nguyễn

    Đạt Nguyễn Vietnam's Gsm Team

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    1,112
    Đã được thích:
    1,445
    Vâng anh ấy chắc đến cả kho rồi chứ :D
     
  16. Quang94

    Quang94 Active Member

    Tham gia ngày:
    3 Tháng tám 2013
    Bài viết:
    439
    Đã được thích:
    66
    A hoangnova có cách nào thêm thanh điều chỉnh âm lượng media lên notification expand giống thanh điều chỉnh ánh sáng ko?

    Sent from my LG-F160 using LG Việt mobile app
     
  17. Văn Chức

    Văn Chức Life Good

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    7,613
    Đã được thích:
    4,920
    Có chứ bạn.
     
  18. hoangnova

    hoangnova Captain Staff Member

    Tham gia ngày:
    20 Tháng năm 2013
    Bài viết:
    6,738
    Đã được thích:
    15,889
    E nên bắt đầu từ thứ dễ hơn, nếu ko tẩu hỏa nhập ma hoặc đi vào ngõ cụt thì nản lòng.
     
  19. hoangnova

    hoangnova Captain Staff Member

    Tham gia ngày:
    20 Tháng năm 2013
    Bài viết:
    6,738
    Đã được thích:
    15,889
    Thêm cái đó làm gì, chật chội ra, volume có 2 phím mà vẫn muốn cho lên làm gì.
     
  20. Văn Chức

    Văn Chức Life Good

    Tham gia ngày:
    8 Tháng sáu 2013
    Bài viết:
    7,613
    Đã được thích:
    4,920
    Bạn Đạt Nguyễn ở đâu vậy ?
     

Chia sẻ trang này