package main import ( "bytes" "fmt" "github.com/BurntSushi/toml" "log" "os" "os/exec" "reflect" "strings" "sync" ) var wg sync.WaitGroup var config Config var ConfigPath string = "./conf.toml" func reflectFn(x interface{}){ v := reflect.TypeOf(x) fmt.Println(v) } func ConnectAdbShell(PackageName string){ str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) in := bytes.NewBuffer(nil) path := str + "/tools/adb.exe" backUpPath := str + "/backup" cmd := exec.Command(path,"shell") cmd.Stdin = in cmd.Stderr = os.Stderr cmd.Stdout= os.Stdout go func() { in.WriteString("cd /data/data\n") in.WriteString("ls\n") pull := path + " pull " + "/data/data/" + PackageName + " " + backUpPath + "/" + PackageName fmt.Println(pull) in.WriteString("cd /\n") in.WriteString("exit\n") in.WriteString(pull + "\n") }() if err := cmd.Run(); err != nil { fmt.Println(err) return } } func CmdPull(PackageName string, DirPath string){ str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" backUpPath := str + "/backup" cmd := exec.Command(path, "pull", "/" + DirPath +"/" + PackageName, backUpPath + "/" + PackageName) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output,err := cmd.Output() if err != nil{ fmt.Println(err) } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) } func CmdPush(PackageName string, DirPath string) { str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" backUpPath := str + "/backup" cmd := exec.Command(path, "push", backUpPath+"/"+DirPath+"/"+PackageName, "/"+DirPath+"/"+PackageName) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output, err := cmd.Output() if err != nil { fmt.Println(err) } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) wg.Done() } func tar(PackageName string, DirPath string) bool { str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" cmd := exec.Command(path, "shell", "tar", "-vcf", "/" + DirPath +"/" + PackageName + DirPath[0:1] + ".tar", "/" + DirPath +"/" + PackageName) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output,err := cmd.Output() if err != nil{ fmt.Println(err) return false } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) return true } func DeleteDir(DirPath string){ str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" cmd := exec.Command(path, "shell", "rm", "-r", DirPath) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output,err := cmd.Output() if err != nil{ fmt.Println(err) } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) } func DeleteFile(FilePath string){ str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" cmd := exec.Command(path, "shell", "rm", FilePath) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output,err := cmd.Output() if err != nil{ fmt.Println(err) } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) } func Release(PackageName string) { str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/7-Zip/7z.exe" backUpPath := str + "/backup/" cmd := exec.Command(path, "x", backUpPath + PackageName, "-o" + backUpPath) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output,err := cmd.Output() if err != nil{ fmt.Println(err) } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) } func PullGameFile(PackageName string, Device bool){ //压缩游戏包 if tar(PackageName, "data/data"){ if !Device{ //删除游戏包 /data/data DeleteDir("/data/data/" + PackageName) } } if tar(PackageName, "sdcard/Android/data"){ if !Device{ //删除游戏包 /sdcard/Android/data DeleteDir("/sdcard/Android/data/" + PackageName) } } //拉取游戏压缩包 CmdPull(PackageName + "d.tar", "data/data") CmdPull(PackageName + "s.tar", "sdcard/Android/data") //删除压缩包 DeleteFile( "/data/data/" + PackageName + "d.tar") DeleteFile("/sdcard/Android/data/" + PackageName + "s.tar") //解压 Release(PackageName + "d.tar") Release(PackageName + "s.tar") } func DeleteGameFile(PackageName string){ // 获取安装包路径 str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) DataPath := str + "/backup/data/data/" + PackageName Sdcard := str + "/backup/sdcard/Android/data/" + PackageName fmt.Println("DeleteGameFile:", DataPath) err := os.RemoveAll(DataPath) if err != nil{ fmt.Println("DeleteGameFile:", err) } fmt.Println("DeleteGameFile:", Sdcard) os.RemoveAll(Sdcard) err = os.RemoveAll(DataPath) if err != nil{ fmt.Println("DeleteGameFile:", err) } } func PackageIsExist(PackageName string, Device bool) bool { // 获取安装包路径 str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) packagePath := str + "/backup/package/" if Device{ packagePath = packagePath + PackageName + "_pc.apk" return PathExists(packagePath) }else { packagePath = packagePath + PackageName + "_arm.apk" return PathExists(packagePath) } } func PullGamePackage(PackageName string, Device bool) { // 获取安装包路径 str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" packagePath := str + "/backup/package/" in := bytes.NewBuffer(nil) cmd := exec.Command(path,"shell") cmd.Stdin = in cmd.Stderr = os.Stderr out := bytes.NewBuffer(nil) cmd.Stdout = out in.WriteString("pm path " + PackageName + "\n") if err := cmd.Run(); err != nil { fmt.Println(err) return } packagePathAdb := strings.Split(out.String(),":")[1] packagePathAdb = strings.Replace(packagePathAdb, "\n", "", -1) packagePathAdb = strings.Replace(packagePathAdb, "\r", "", -1) if Device{ packagePath = packagePath + PackageName + "_pc.apk" }else { packagePath = packagePath + PackageName + "_arm.apk" } Chmod(packagePathAdb, Device) //拉取安装包 cmd = exec.Command(path, "pull", string(packagePathAdb), packagePath) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output, err := cmd.Output() if err != nil { fmt.Println(err) } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) wg.Done() } func Chmod(dir string, DeviceIsPc bool) { str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" //安装安装包 if DeviceIsPc{ cmd := exec.Command(path, "shell", "chmod","-R","777", dir) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output, err := cmd.Output() if err != nil { fmt.Println(err) return } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) fmt.Println("chmod is Ok") }else { cmd := exec.Command(path, "shell", "su","-c", "chmod","-R","777", dir) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output, err := cmd.Output() if err != nil { fmt.Println(err) return } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) fmt.Println("chmod is Ok") } } func PushGamePackage(PackageName string, Device bool) { str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" var packagePath string if Device{ packagePath = str + "/backup/package/" + PackageName + "_pc.apk" }else { packagePath = str + "/backup/package/" + PackageName + "_arm.apk" } //安装安装包 cmd := exec.Command(path, "install", "-r", packagePath) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output, err := cmd.Output() if err != nil { fmt.Println(err) } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) } func UninstallGamePackage(PackageName string){ str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/tools/adb.exe" //卸载安装包 cmd := exec.Command(path, "uninstall", PackageName) fmt.Println(cmd) // 执行命令,并返回结果 cmd.Stderr = os.Stderr output, err := cmd.Output() if err != nil { fmt.Println(err) } // 因为结果是字节数组,需要转换成string fmt.Print(string(output)) } func PushGameFile(PackageName string) { wg.Add(1) go CmdPush(PackageName, "data/data") wg.Add(1) go CmdPush(PackageName, "sdcard/Android/data") wg.Done() } func CreateFile(folderPath string){ str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) path := str + "/" + folderPath if _, err := os.Stat(path); os.IsNotExist(err) { // 必须分成两步 // 先创建文件夹 os.Mkdir(path, 0777) // 再修改权限 os.Chmod(path, 0777) } } func Init(PackageName string,tasksChan chan string, Device bool)bool{ /** 创建必要文件夹: backup:存放备份的文件 backup/data/data:存放/data/data下的游戏文件 backup/sdcard/Android/data:存放/sdcard/Android/data下的游戏文件 backup/package:游戏安装包 */ CreateFile("backup") CreateFile("backup/data") CreateFile("backup/data/data") CreateFile("backup/sdcard") CreateFile("backup/sdcard/Android") CreateFile("backup/sdcard/Android/data") CreateFile("backup/package") fmt.Println("init Ok!") //执行操作 for{ select { case operation := <- tasksChan: if operation == "backup" { fmt.Println("backup:") if config.BackupPackage{ //拉取备份apk if !PackageIsExist(PackageName, Device){ wg.Add(1) go PullGamePackage(PackageName, Device) } if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } } //拉取手机游戏包名文件 //赋予权限 Chmod("/data/data/" + PackageName, Device) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } Chmod("/sdcard/Android/data/" + PackageName, Device) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } //删除以前的游戏包文件 DeleteGameFile(PackageName) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } PullGameFile(PackageName, Device) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } wg.Wait() } if operation == "recovery" { //上传已备份的游戏包 //判断游戏包是否存在 fmt.Println("recovery:") if FileExists(PackageName){ //上传 PushGamePackage(PackageName, Device) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } fmt.Println("chmod get:") //赋予权限 Chmod("/data/data/" + PackageName, Device) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } Chmod("/sdcard/Android/data/" + PackageName, Device) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } wg.Add(1) go PushGameFile(PackageName) wg.Wait() if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } //赋予权限 Chmod("/data/data/" + PackageName, Device) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } Chmod("/sdcard/Android/data/" + PackageName, Device) if config.Debug{ fmt.Println("输入任意键继续,input Enter continue") fmt.Scanln() } }else { fmt.Println("fail") return false } } if operation == "uninstall"{ //卸载安装包 UninstallGamePackage(PackageName) //如果有本地游戏文件卸载 } if operation == "all" { tasksChan <- "backup" tasksChan <- "uninstall" tasksChan <- "recovery" } default: wg.Wait() return true } } } func FileExists(PackageName string)bool{ str, _ := os.Getwd() str = strings.Replace(str, "\\", "/", -1) backUpPath := str + "/backup" dataPath := backUpPath + "/data/data/" + PackageName sdcardPath := backUpPath + "/sdcard/Android/data/" + PackageName data := PathExists(dataPath) sdcard := PathExists(sdcardPath) if !data{ fmt.Println(dataPath + " Not Exists") return false } if !sdcard{ fmt.Println(sdcardPath + " Not Exists") return false } return true } func PathExists(path string) bool { _, err := os.Stat(path) if err == nil { return true } if os.IsNotExist(err) { return false } return false } type Config struct { PackageName string Operation string Debug bool Device bool BackupPackage bool } func main() { if _, err := toml.DecodeFile(ConfigPath, &config); err != nil { log.Fatal(err) } fmt.Printf("PackageName:%v\tOperation:%v\n", config.PackageName, config.Operation) //设置包名 var PackageName = config.PackageName tasksChan := make(chan string, 5) tasksChan <- config.Operation //初始化程序, 程序入口 if Init(PackageName, tasksChan, config.Device){ fmt.Println("Complete!") }else { fmt.Println("Error") } if config.Debug{ fmt.Println("输入回车退出程序,input Enter quit program") } }