diff --git a/hrp/internal/version/VERSION b/hrp/internal/version/VERSION index f4d009b8..488312ea 100644 --- a/hrp/internal/version/VERSION +++ b/hrp/internal/version/VERSION @@ -1 +1 @@ -v4.5.7 \ No newline at end of file +v4.5.8 \ No newline at end of file diff --git a/hrp/pkg/uixt/action.go b/hrp/pkg/uixt/action.go index 3ec9a3cd..12541954 100644 --- a/hrp/pkg/uixt/action.go +++ b/hrp/pkg/uixt/action.go @@ -28,6 +28,7 @@ const ( ACTION_StopCamera ActionMethod = "camera_stop" // alias for app_terminate camera ACTION_SetClipboard ActionMethod = "set_clipboard" ACTION_GetClipboard ActionMethod = "get_clipboard" + ACTION_SetIme ActionMethod = "set_ime" // UI validation // selectors @@ -607,6 +608,14 @@ func (dExt *DriverExt) DoAction(action MobileAction) (err error) { return fmt.Errorf("set_clioboard params should be text(string), got %v", action.Params) case ACTION_Home: return dExt.Driver.Homescreen() + case ACTION_SetIme: + if ime, ok := action.Params.(string); ok { + err = dExt.Driver.SetIme(ime) + if err != nil { + return errors.Wrap(err, "failed to set ime") + } + return nil + } case ACTION_TapXY: if location, ok := action.Params.([]interface{}); ok { // relative x,y of window size: [0.5, 0.5] diff --git a/hrp/pkg/uixt/android_adb_driver.go b/hrp/pkg/uixt/android_adb_driver.go index c642a245..43d756eb 100644 --- a/hrp/pkg/uixt/android_adb_driver.go +++ b/hrp/pkg/uixt/android_adb_driver.go @@ -421,6 +421,14 @@ func (ad *adbDriver) IsUnicodeIMEInstalled() bool { return strings.Contains(output, UnicodeImePackageName) } +func (ad *adbDriver) ListIme() []string { + output, err := ad.adbClient.RunShellCommand("ime", "list", "-s") + if err != nil { + return []string{} + } + return strings.Split(output, "\n") +} + func (ad *adbDriver) SendKeysByAdbKeyBoard(text string) (err error) { defer func() { // Reset to default, don't care which keyboard was chosen before switch: @@ -715,11 +723,61 @@ func (ad *adbDriver) GetForegroundApp() (app AppInfo, err error) { return AppInfo{}, errors.Wrap(code.MobileUIAssertForegroundAppError, "get foreground app failed") } -func (ad *adbDriver) SetIme(ime string) error { - _, err := ad.adbClient.RunShellCommand("ime", "set", ime) +func (ad *adbDriver) GetFocusedPackage() (packageName string, err error) { + res, err := ad.adbClient.RunShellCommand("dumpsys", "window", "windows", "|", "grep", "-E", "'mCurrentFocus|mFocusedApp'") + if err != nil { + return "", err + } + match := regexp.MustCompile("mCurrentFocus.+\\s([^\\s/}]+)/[^\\s/}]+(\\.[^\\s/}]+)}").FindStringSubmatch(res) + if len(match) > 1 { + packageName = match[1] + return + } + match = regexp.MustCompile("mFocusedApp.+Record\\{.*\\s([^\\s/}]+)/([^\\s/}]+)(\\s[^\\s/}]+)*}").FindStringSubmatch(res) + if len(match) > 1 { + packageName = match[1] + return + } + log.Error().Str("dumpsys", res).Msg("failed to get focused package") + return "", fmt.Errorf("failed to get focused package") +} + +func (ad *adbDriver) SetIme(imeRegx string) error { + imeList := ad.ListIme() + ime := "" + for _, imeName := range imeList { + if regexp.MustCompile(imeRegx).MatchString(imeName) { + ime = imeName + break + } + } + if ime == "" { + return fmt.Errorf("failed to set ime by %s, ime list: %v", imeRegx, imeList) + } + brand, _ := ad.adbClient.Brand() + packageName := strings.Split(ime, "/")[0] + res, err := ad.adbClient.RunShellCommand("ime", "set", ime) + log.Info().Str("funcName", "SetIme").Interface("ime", ime). + Interface("output", res).Msg("set ime") if err != nil { return err } + + if strings.ToLower(brand) == "oppo" { + pid, _ := ad.adbClient.RunShellCommand("pidof", packageName) + if strings.TrimSpace(pid) == "" { + focusedPackage, err := ad.GetFocusedPackage() + _ = ad.AppLaunch(packageName) + if err == nil && packageName != UnicodeImePackageName { + time.Sleep(10 * time.Second) + currentPackage, err := ad.GetFocusedPackage() + log.Info().Str("beforeFocusedPackage", focusedPackage).Str("afterFocusedPackage", currentPackage).Msg("") + if err == nil && currentPackage != focusedPackage { + _ = ad.PressKeyCode(KCBack, KMEmpty) + } + } + } + } // even if the shell command has returned, // as there might be a situation where the input method has not been completely switched yet // Listen to the following message. diff --git a/hrp/pkg/uixt/android_device.go b/hrp/pkg/uixt/android_device.go index c754c52a..20e8ffa0 100644 --- a/hrp/pkg/uixt/android_device.go +++ b/hrp/pkg/uixt/android_device.go @@ -159,15 +159,8 @@ type AndroidDevice struct { } func (dev *AndroidDevice) Init() error { - brand, err := dev.d.Brand() - if err != nil { - return fmt.Errorf("failed to init android device. brand is null %v", err) - } - if strings.ToLower(brand) == "oppo" { - // 启动一次io.appium.settings。防止oppo设备上切换输入法失败 - myexec.RunCommand("adb", "-s", dev.SerialNumber, "shell", - "monkey", "-p", "io.appium.settings", "-c", "android.intent.category.LAUNCHER", "1") - } + myexec.RunCommand("adb", "-s", dev.SerialNumber, "shell", + "ime", "enable", "io.appium.settings/.UnicodeIME") myexec.RunCommand("adb", "-s", dev.SerialNumber, "shell", "rm", "-r", env.DeviceActionLogFilePath) return nil } diff --git a/hrp/pkg/uixt/interface.go b/hrp/pkg/uixt/interface.go index 5a93b5bf..1df9dbca 100644 --- a/hrp/pkg/uixt/interface.go +++ b/hrp/pkg/uixt/interface.go @@ -572,6 +572,8 @@ type WebDriver interface { // It worked when `WDA` was foreground. https://github.com/appium/WebDriverAgent/issues/330 GetPasteboard(contentType PasteboardType) (raw *bytes.Buffer, err error) + SetIme(ime string) error + // SendKeys Types a string into active element. There must be element with keyboard focus, // otherwise an error is raised. // WithFrequency option can be used to set frequency of typing (letters per sec). The default value is 60 diff --git a/hrp/pkg/uixt/ios_driver.go b/hrp/pkg/uixt/ios_driver.go index 9acc164c..80e80a46 100644 --- a/hrp/pkg/uixt/ios_driver.go +++ b/hrp/pkg/uixt/ios_driver.go @@ -591,6 +591,10 @@ func (wd *wdaDriver) GetPasteboard(contentType PasteboardType) (raw *bytes.Buffe return } +func (wd *wdaDriver) SetIme(ime string) error { + return errDriverNotImplemented +} + func (wd *wdaDriver) SendKeys(text string, options ...ActionOption) (err error) { // [[FBRoute POST:@"/wda/keys"] respondWithTarget:self action:@selector(handleKeys:)] actionOptions := NewActionOptions(options...)