Compare commits
3 Commits
4304a92a53
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e8b31eb263 | |||
| 53cf344cc0 | |||
| 40af079fd2 |
61
app.go
Normal file
61
app.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package goadb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Get the current focussed app package name
|
||||
func (d *Device) GetCurrentAppPackage() (string, error) {
|
||||
data, err := d.RunCommand("shell dumpsys activity activities | grep ResumedActivity")
|
||||
re := regexp.MustCompile(`\b([a-zA-Z0-9._]+)/(?:[a-zA-Z0-9._]+)\b`)
|
||||
matches := re.FindStringSubmatch(string(data))
|
||||
|
||||
if len(matches) > 1 {
|
||||
return matches[1], nil
|
||||
} else {
|
||||
return "", nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Get the pid for a app
|
||||
func (d *Device) GetAppPid(appackage string) (int, error) {
|
||||
data, err := d.RunCommand(fmt.Sprintf("shell pidof %s"))
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return pid, nil
|
||||
}
|
||||
|
||||
// Check if a app is running
|
||||
func (d *Device) CheckAppRunning(appackage string) (bool, error) {
|
||||
pid, err := d.GetAppPid(appackage)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if pid != -1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Start a app using the package name
|
||||
func (d *Device) StartApp(appackage string) error {
|
||||
_, err := d.RunCommand(fmt.Sprintf("shell monkey -p %s -c android.intent.category.LAUNCHER 1", appackage))
|
||||
return err
|
||||
}
|
||||
|
||||
// Force kill a running app
|
||||
func (d *Device) KillApp(appackage string) error {
|
||||
_, err := d.RunCommand(fmt.Sprintf("shell am force-stop %s", appackage))
|
||||
return err
|
||||
}
|
||||
58
screen.go
58
screen.go
@@ -28,6 +28,12 @@ func (d *Device) ToggleScreen() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Tap on a location on the screen
|
||||
func (d *Device) TapScreen(x int, y int) error {
|
||||
_, err := d.RunCommand(fmt.Sprintf("shell input tap %d %d", x, y))
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the resolution of the screen
|
||||
func (d *Device) GetScreenResolution() (int, int, error) {
|
||||
|
||||
@@ -61,21 +67,17 @@ func (d *Device) GetScreenResolution() (int, int, error) {
|
||||
return d.Screenx, d.Screeny, nil
|
||||
}
|
||||
|
||||
// Get the text on screen in a certain area using gotesseract
|
||||
func (d *Device) GetScreenText(xStart int, xEnd int, yStart int, yEnd int, whitelist string, multiline bool) (string, error) {
|
||||
// Take screenshot in memory and get bytes
|
||||
func (d *Device) GetScreenText(xStart int, xEnd int, yStart int, yEnd int, whitelist string, multiline bool, textPolarity string) (string, error) {
|
||||
data, err := d.RunCommand("exec-out screencap -p")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to take screenshot: %w", err)
|
||||
}
|
||||
|
||||
// Decode image from bytes
|
||||
img, err := png.Decode(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode PNG: %w", err)
|
||||
}
|
||||
|
||||
// Crop region
|
||||
rect := image.Rect(0, 0, xEnd-xStart, yEnd-yStart)
|
||||
cropped := image.NewRGBA(rect)
|
||||
for y := yStart; y < yEnd; y++ {
|
||||
@@ -84,27 +86,57 @@ func (d *Device) GetScreenText(xStart int, xEnd int, yStart int, yEnd int, white
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to grayscale and apply threshold
|
||||
threshold := uint8(160)
|
||||
// Convert to grayscale and compute average brightness
|
||||
gray := image.NewGray(rect)
|
||||
var totalBrightness int
|
||||
for y := 0; y < rect.Dy(); y++ {
|
||||
for x := 0; x < rect.Dx(); x++ {
|
||||
grayVal := color.GrayModel.Convert(cropped.At(x, y)).(color.Gray)
|
||||
gray.Set(x, y, grayVal)
|
||||
totalBrightness += int(grayVal.Y)
|
||||
}
|
||||
}
|
||||
avgBrightness := totalBrightness / (rect.Dx() * rect.Dy())
|
||||
|
||||
// Decide polarity
|
||||
useLightText := false
|
||||
switch textPolarity {
|
||||
case "light":
|
||||
useLightText = true
|
||||
case "dark":
|
||||
useLightText = false
|
||||
case "auto":
|
||||
useLightText = avgBrightness < 128
|
||||
default:
|
||||
return "", fmt.Errorf("invalid textPolarity: must be 'dark', 'light', or 'auto'")
|
||||
}
|
||||
|
||||
// Binarize based on polarity
|
||||
binarized := image.NewGray(rect)
|
||||
for y := 0; y < rect.Dy(); y++ {
|
||||
for x := 0; x < rect.Dx(); x++ {
|
||||
gray := color.GrayModel.Convert(cropped.At(x, y)).(color.Gray)
|
||||
if gray.Y > threshold {
|
||||
binarized.SetGray(x, y, color.Gray{Y: 255})
|
||||
} else {
|
||||
grayVal := gray.GrayAt(x, y).Y
|
||||
if useLightText {
|
||||
if int(grayVal) > avgBrightness+10 {
|
||||
binarized.SetGray(x, y, color.Gray{Y: 0})
|
||||
} else {
|
||||
binarized.SetGray(x, y, color.Gray{Y: 255})
|
||||
}
|
||||
} else {
|
||||
if int(grayVal) < avgBrightness-10 {
|
||||
binarized.SetGray(x, y, color.Gray{Y: 0})
|
||||
} else {
|
||||
binarized.SetGray(x, y, color.Gray{Y: 255})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Encode binarized image to PNG
|
||||
var buf bytes.Buffer
|
||||
if err := png.Encode(&buf, binarized); err != nil {
|
||||
return "", fmt.Errorf("failed to encode image: %w", err)
|
||||
}
|
||||
|
||||
// Call tesseract
|
||||
client := gosseract.NewClient()
|
||||
defer client.Close()
|
||||
client.SetImageFromBytes(buf.Bytes())
|
||||
|
||||
Reference in New Issue
Block a user