Commit a68566a7 authored by liuyang's avatar liuyang

APK图片抓取识别及轮播流地址抓取,ftp上传处理

#BYLSERVER-1438
parent 661cd827
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:name=".DlbRobotApp"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"launchDelay": "15", "launchDelay": "15",
"captureDelay": "15", "captureDelay": "15",
"channelKeyEvent": "down", "channelKeyEvent": "down",
"channelCount": "10", "channelCount": "2",
"mediaExt": "m3u8|.mp4", "mediaExt": "m3u8|.mp4",
"menuKeyEvent": "ok" "menuKeyEvent": "ok"
} }
\ No newline at end of file
package com.duolebo.blyrobot
import android.app.Application
import net.gotev.uploadservice.UploadService
import net.gotev.uploadservice.okhttp.OkHttpStack
import okhttp3.OkHttpClient
class DlbRobotApp: Application() {
override fun onCreate() {
super.onCreate()
UploadService.NAMESPACE = BuildConfig.APPLICATION_ID
UploadService.NAMESPACE = this.packageName
val client = OkHttpClient()
UploadService.HTTP_STACK = OkHttpStack(client)
}
}
\ No newline at end of file
...@@ -10,8 +10,12 @@ import com.duolebo.blyrobot.protocol.ApkReportProtocol ...@@ -10,8 +10,12 @@ import com.duolebo.blyrobot.protocol.ApkReportProtocol
import com.duolebo.blyrobot.util.AdbUtil import com.duolebo.blyrobot.util.AdbUtil
import com.duolebo.blyrobot.util.AppUtil import com.duolebo.blyrobot.util.AppUtil
import com.duolebo.blyrobot.util.Config import com.duolebo.blyrobot.util.Config
import net.gotev.uploadservice.ServerResponse
import net.gotev.uploadservice.UploadInfo
import net.gotev.uploadservice.UploadNotificationConfig import net.gotev.uploadservice.UploadNotificationConfig
import net.gotev.uploadservice.UploadStatusDelegate
import net.gotev.uploadservice.ftp.FTPUploadRequest import net.gotev.uploadservice.ftp.FTPUploadRequest
import net.gotev.uploadservice.ftp.UnixPermissions
import org.json.JSONObject import org.json.JSONObject
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
...@@ -30,6 +34,8 @@ class Task : IAppBaseCallback { ...@@ -30,6 +34,8 @@ class Task : IAppBaseCallback {
private var capturePath = Environment private var capturePath = Environment
.getExternalStorageDirectory().absolutePath + "/capture.txt" .getExternalStorageDirectory().absolutePath + "/capture.txt"
private var uploadImages = ArrayList<String>()
private var channelIndex = 0 private var channelIndex = 0
private var reportProtocol: ApkReportProtocol private var reportProtocol: ApkReportProtocol
...@@ -50,7 +56,7 @@ class Task : IAppBaseCallback { ...@@ -50,7 +56,7 @@ class Task : IAppBaseCallback {
this.apkInfo = apkInfo this.apkInfo = apkInfo
// this.imagePath = this.context.cacheDir.absolutePath + "/" + apkInfo.packageName // this.imagePath = this.context.cacheDir.absolutePath + "/" + apkInfo.packageName
this.imagePath = Environment this.imagePath = Environment
.getExternalStorageDirectory().absolutePath + "/" + apkInfo.packageName .getExternalStorageDirectory().absolutePath + "/upload/" + apkInfo.packageName
val dir = File(this.imagePath) val dir = File(this.imagePath)
if (!dir.exists()) if (!dir.exists())
dir.mkdirs() dir.mkdirs()
...@@ -82,29 +88,34 @@ class Task : IAppBaseCallback { ...@@ -82,29 +88,34 @@ class Task : IAppBaseCallback {
} }
AdbUtil.launchApp("${this.apkInfo.packageName}/${this.apkInfo.launcher}") AdbUtil.launchApp("${this.apkInfo.packageName}/${this.apkInfo.launcher}")
Thread.sleep(2 * 1000L)
// 启动2s开始抓取,避免第一个频道没有抓到
capture(this.apkInfo.launchDelay + this.apkInfo.captureDelay)
Thread.sleep(this.apkInfo.launchDelay * 1000L) Thread.sleep(this.apkInfo.launchDelay * 1000L)
} }
private fun processChannels() { private fun processChannels() {
Log.i(TAG, "processChannels") Log.i(TAG, "processChannels")
step() step()
for (i in 1..this.apkInfo.channelCount) { for (i in 1 until this.apkInfo.channelCount) {
// 模拟按键事件. 切换频道进行抓取 // 模拟按键事件. 切换频道进行抓取
this.channelIndex = i this.channelIndex = i
capture(apkInfo.captureDelay)
AdbUtil.sendMultiKey(this.apkInfo.channelKeyEvent) AdbUtil.sendMultiKey(this.apkInfo.channelKeyEvent)
step() step()
} }
} }
private fun step() { private fun step() {
capture()
// 截图保存 // 截图保存
val screenShots = saveScreenShot() val screenShots = saveScreenShot()
if (screenShots.size > 0)
uploadImages.addAll(screenShots)
val playUrlItems = analysisCapture() val playUrlItems = analysisCapture()
} }
// 抓包处理 // 抓包处理
private fun capture() { private fun capture(delay: Int) {
Log.i(TAG, "capture") Log.i(TAG, "capture")
val file = File(this.capturePath) val file = File(this.capturePath)
if (file.exists()) if (file.exists())
...@@ -112,8 +123,8 @@ class Task : IAppBaseCallback { ...@@ -112,8 +123,8 @@ class Task : IAppBaseCallback {
Thread(Runnable { Thread(Runnable {
proc = AdbUtil.tcpCapture(this.capturePath) proc = AdbUtil.tcpCapture(this.capturePath)
}).start() }).start()
Log.i(TAG, "capture sleep ${this.apkInfo.captureDelay} seconds") Log.i(TAG, "capture sleep $delay seconds")
Thread.sleep(this.apkInfo.captureDelay * 1000L) Thread.sleep(delay * 1000L)
proc?.destroy() proc?.destroy()
AdbUtil.killTcpdump() AdbUtil.killTcpdump()
Thread.sleep(2000L) Thread.sleep(2000L)
...@@ -122,8 +133,10 @@ class Task : IAppBaseCallback { ...@@ -122,8 +133,10 @@ class Task : IAppBaseCallback {
// 分析http抓包文件 // 分析http抓包文件
private fun analysisCapture(): ArrayList<PlayInfo> { private fun analysisCapture(): ArrayList<PlayInfo> {
val playUrlItems = ArrayList<PlayInfo>() val playUrlItems = ArrayList<PlayInfo>()
val file = File(Environment val file = File(this.capturePath)
.getExternalStorageDirectory().absolutePath + "/capture.txt") if (!file.exists())
return playUrlItems
val lines = file.readLines() val lines = file.readLines()
var partUrl = "" var partUrl = ""
...@@ -206,24 +219,62 @@ class Task : IAppBaseCallback { ...@@ -206,24 +219,62 @@ class Task : IAppBaseCallback {
AppUtil.pngToJpg(pngPath, jpgPath) AppUtil.pngToJpg(pngPath, jpgPath)
} }
private fun uploadComplete(errorCount: Int) {
report()
}
private fun uploadImageCallback(): UploadStatusDelegate {
val totalUpload = this.uploadImages.size
var uploadCount = 0
return object: UploadStatusDelegate {
override fun onCancelled(context: Context?, uploadInfo: UploadInfo?) {
}
override fun onProgress(context: Context?, uploadInfo: UploadInfo?) {
}
override fun onError(context: Context?, uploadInfo: UploadInfo?, serverResponse: ServerResponse?, exception: java.lang.Exception?) {
Log.i(TAG, "upload error " + uploadInfo?.toString())
uploadCount++
if (uploadCount == totalUpload) {
uploadComplete(uploadCount - uploadInfo?.successfullyUploadedFiles!!.size)
}
}
override fun onCompleted(context: Context?, uploadInfo: UploadInfo?, serverResponse: ServerResponse?) {
uploadCount++
if (uploadCount == totalUpload) {
uploadComplete(uploadCount - uploadInfo?.successfullyUploadedFiles!!.size)
}
}
}
}
private fun uploadImage() { private fun uploadImage() {
try { try {
val uploadRequest = FTPUploadRequest(context, "ftp.duolebo.com", 21) val uploadRequest = FTPUploadRequest(context, Config.instance.getFtpServer(), 21)
.setUsernameAndPassword("user", "password") .setUsernameAndPassword(Config.instance.getFtpUserName(), Config.instance.getFtpPassword())
.setNotificationConfig(UploadNotificationConfig()) .setNotificationConfig(UploadNotificationConfig())
.setCreatedDirectoriesPermissions(UnixPermissions("777"))
.setSocketTimeout(5000)
.setConnectTimeout(5000)
.setDelegate(uploadImageCallback())
.setMaxRetries(4) .setMaxRetries(4)
val dir = File(imagePath) this.uploadImages.forEach {
dir.listFiles().forEach { val uploadFile = File(it)
uploadRequest.addFileToUpload(it.absolutePath, "/remote/path") if (uploadFile.exists()) {
uploadRequest.addFileToUpload(it, Config.instance.getFtpRemotePath())
}
} }
val uploadId = uploadRequest.startUpload() val uploadId = uploadRequest.startUpload()
Log.i(TAG, "upload id $uploadId") Log.i(TAG, "upload id $uploadId")
} catch (exc: Exception) { } catch (exc: Exception) {
Log.e("AndroidUploadService", exc.message, exc) Log.e(TAG, exc.message, exc)
} }
} }
private fun report() { private fun report() {
......
...@@ -55,7 +55,9 @@ class TaskManager { ...@@ -55,7 +55,9 @@ class TaskManager {
} }
fun stop() { fun stop() {
this.tasks.clear() this.tasks.forEach {
}
this.isRunning = false this.isRunning = false
} }
......
...@@ -210,6 +210,7 @@ object AdbUtil { ...@@ -210,6 +210,7 @@ object AdbUtil {
try { try {
dos = DataOutputStream(proc!!.outputStream) dos = DataOutputStream(proc!!.outputStream)
dos.write(captureCmd.toByteArray()) dos.write(captureCmd.toByteArray())
dos.writeBytes(LINE_BREAK)
dos.flush() dos.flush()
val result = proc.waitFor() val result = proc.waitFor()
...@@ -292,6 +293,18 @@ object AdbUtil { ...@@ -292,6 +293,18 @@ object AdbUtil {
} }
} }
fun isAppActive(packageName: String): Boolean {
val result = exeCmdEcho("dumpsys activity | grep mFocusedActivity", true)
if (result.status == 0) {
for (line in result.successLines) {
if (line.contains(packageName))
return true
}
}
return false
}
fun resetApp(packageName: String) { fun resetApp(packageName: String) {
exeCmdEcho("pm clear $packageName", true) exeCmdEcho("pm clear $packageName", true)
} }
......
...@@ -25,6 +25,22 @@ class Config: IProtocolConfig { ...@@ -25,6 +25,22 @@ class Config: IProtocolConfig {
return "http://test.duolebo.com/staging/apkReport/report.do" return "http://test.duolebo.com/staging/apkReport/report.do"
} }
fun getFtpServer(): String {
return "192.168.2.195"
}
fun getFtpUserName(): String {
return "mateng"
}
fun getFtpPassword(): String {
return "qwertasdfg"
}
fun getFtpRemotePath(): String {
return "/upload"
}
companion object { companion object {
val instance = Config() val instance = Config()
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment