This repository has been archived on 2024-09-30. You can view files and clone it, but cannot push or open issues/pull-requests.
IkuTerminal/TTT/TTTask.java

920 lines
40 KiB
Java

package com.bytedance.ttcollector.utils;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
import android.util.Log;
import android.util.Pair;
import androidx.core.content.FileProvider;
import com.mysql.jdbc.Statement;
import com.sound.apksource.ApkSource;
import com.sound.duoapks.ApkSourceBuilder;
import com.sound.filedescriptor.FlexSaiPackageInstaller;
import com.sound.filedescriptor.PreferencesHelper;
import com.sound.filedescriptor.SaiPiSessionParams;
import com.sound.shell.RootedSaiPackageInstaller;
import com.yanzhenjie.andserver.util.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import de.robv.android.xposed.XposedBridge;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class TTTask {
public static Boolean _installRet;
public static Boolean _paused;
private static String TAG = "AFTask";
private final Context _context;
private final String _appid;
private final String _downloadUrl;
private Connection _dbConn;
private Statement _dbStat;
private static boolean go = false;
static {
_installRet = null;
_paused = false;
}
public TTTask(Context context, String appid, String downloadUrl) throws Throwable {
_context = context;
_appid = appid;
_downloadUrl = downloadUrl;
}
/**
* 获取apk文件名
* @param appid
* @return
* @throws Throwable
*/
private String apkFileName(String appid) throws Throwable{
String result = "";
String sql="SELECT ApkPath FROM apkinfo1 WHERE PackageName = '" + appid + "';";
ResultSet rs=_dbStat.executeQuery(sql);
if(rs.next()){
result = rs.getString("ApkPath");
}
rs.close();
return result;
}
/**
* 下载APk
* @param downloadUrl
* @param fileName
* @return
* @throws Throwable
*/
private String downloadAPK(String downloadUrl, String fileName) throws Throwable {
Log.d("AFTask", "downloadAPK: " + Environment.getExternalStorageState());
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
String sdPath = Environment.getExternalStorageDirectory() + "/";
String savePath = sdPath + "aftask";
File dir = new File(savePath);
if (!dir.exists()){
Process process = Runtime.getRuntime().exec("su");
PrintWriter PrintWriter = new PrintWriter(process.getOutputStream());
PrintWriter.println("mkdir " + sdPath + "aftask");
PrintWriter.println("chmod 777 " + sdPath + "aftask");
PrintWriter.flush();
PrintWriter.close();
process.waitFor();
}
// 下载文件
HttpURLConnection conn = (HttpURLConnection) new URL(downloadUrl + fileName).openConnection();
conn.connect();
InputStream is = conn.getInputStream();
File apkFile = new File(savePath, fileName);
FileOutputStream fos = new FileOutputStream(apkFile);
byte[] buffer = new byte[10240];
while (true) {
int numread = is.read(buffer);
if (numread < 0){ break; }
fos.write(buffer, 0, numread);
}
fos.close();
is.close();
return apkFile.getPath();
}
return "";
}
private static boolean returnResult(int value){
// 代表成功
if (value == 0) {
return true;
} else if (value == 1) { // 失败
return false;
} else { // 未知情况
return false;
}
}
private boolean clientInstallApk(File apkFile){
PrintWriter PrintWriter = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("su");
PrintWriter = new PrintWriter(process.getOutputStream());
PrintWriter.println("chmod 777 " + apkFile);
PrintWriter.println("pm install -r " + apkFile);
PrintWriter.flush();
PrintWriter.close();
int value = process.waitFor();
return returnResult(value);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(process!=null){
process.destroy();
}
}
return false;
}
private boolean clientInstallApks(File apkFile){
Uri uri = Uri.fromFile(apkFile);
FlexSaiPackageInstaller mInstaller = FlexSaiPackageInstaller.getInstance(_context);
PreferencesHelper mPrefsHelper = PreferencesHelper.getInstance(_context);
RootedSaiPackageInstaller rootedSaiPackageInstaller = RootedSaiPackageInstaller.getInstance(_context);
ApkSource apkSource = new ApkSourceBuilder(_context)
.fromZipContentUri(uri)
.setZipExtractionEnabled(mPrefsHelper.shouldExtractArchives())
.setReadZipViaZipFileEnabled(mPrefsHelper.shouldUseZipFileApi())
.setSigningEnabled(mPrefsHelper.shouldSignApks())
.build();
// mInstaller.enqueueSession(mInstaller.createSessionOnInstaller(mPrefsHelper.getInstaller(), new SaiPiSessionParams(apkSource)));
rootedSaiPackageInstaller.enqueueSession(mInstaller.createSessionOnInstaller(mPrefsHelper.getInstaller(), new SaiPiSessionParams(apkSource)));
while(_installRet == null){
try{
Thread.sleep(1000);
}catch (Exception e){}
}
boolean result = _installRet;
_installRet = null;
return result;
}
/**
* 删除APK
* @param apk_file_path
* @return
*/
private boolean deleteAPK(final String apk_file_path) {
try {
File f = new File(apk_file_path);
return f.delete();
}catch (Throwable err){
return false;
}
}
/**
* 卸载APK
* @param packageName
* @return
* @throws Throwable
*/
private boolean clientUninstall(String packageName) {
PrintWriter PrintWriter = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("su");
PrintWriter = new PrintWriter(process.getOutputStream());
PrintWriter.println("pm uninstall " + packageName);
PrintWriter.flush();
PrintWriter.close();
int value = process.waitFor();
return returnResult(value);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(process!=null){
process.destroy();
}
}
return false;
}
/**
* 打开APP
* @param packageName
* @throws Throwable
*/
private boolean openApp(String packageName) {
try{
Global.setTargetAppName(packageName);
Intent intent = _context.getPackageManager().getLaunchIntentForPackage(packageName);
// if(intent != null){
// _context.startActivity(intent);
// return true;
// }else{
// CmdUtils.amStart(getApkMainActivity(packageName));
// return false;
// }
_context.startActivity(intent);
}catch (Throwable e){
e.printStackTrace();
return false;
}
return true;
}
public String getApkMainActivity(String packageName) {
String mainActivity = null;
final PackageManager packageManager = _context.getPackageManager();
PackageInfo pi = null;
try {
pi = _context.getPackageManager().getPackageInfo(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(pi == null || pi.packageName == null){
//Toast.makeText(this, "还没安装!", 2000).show();
Log.d(TAG, "getMainActivity: " + "apk还没安装");
return null;
}
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
resolveIntent.setPackage(pi.packageName);
List<ResolveInfo> apps = packageManager.queryIntentActivities(resolveIntent, 0);
ResolveInfo ri = apps.iterator().next();
if (ri != null) {
String pkgName = ri.activityInfo.packageName;
String className = ri.activityInfo.name;
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(pkgName, className);
Log.d(TAG, "openApp: " + cn.toString());
Log.d(TAG, "openApp: " + cn.toShortString());
Log.d(TAG, "openApp: " + cn.flattenToString());
Log.d(TAG, "openApp: " + cn.flattenToShortString());
mainActivity = cn.flattenToShortString();
// intent.setComponent(cn);
// MyApplication.getContext().startActivity(intent);
}
return mainActivity;
}
/**
* 拷贝日志文件
* @param packageName
* @param maxSecondOfWait
* @return
* @throws Throwable
*/
private boolean copyLogFile(String packageName, long maxSecondOfWait, long minSecondOfWait) throws Throwable {
long begin = System.currentTimeMillis();
Process process = Runtime.getRuntime().exec("su");
PrintWriter printWriter = new PrintWriter(process.getOutputStream());
printWriter.println("chmod 777 /data/data/" + packageName);
printWriter.println("mkdir /data/data/com.bytedance.ttcollector/" + packageName);
printWriter.println("chmod 777 /data/data/com.bytedance.ttcollector/" + packageName);
printWriter.flush();
boolean afCopied = false, adCopied = false;
while ((!afCopied || !adCopied) && (System.currentTimeMillis() - begin <= (maxSecondOfWait * 1000))){
boolean notAF = new File("/data/data/" + packageName + "/AFNOEXISTS.lock").exists();
boolean notAD = new File("/data/data/" + packageName + "/ADNOEXISTS.lock").exists();
if (notAF) {
afCopied = true;
} else {
boolean existsAFVer = new File("/data/data/" + packageName + "/AFVERSION.lock").exists();
boolean existsAFApp = new File("/data/data/" + packageName + "/AFAPP.lock").exists();
boolean existsAFPostT = new File("/data/data/" + packageName + "/AFT.lock").exists();
boolean existsAFPostC = new File("/data/data/" + packageName + "/AFCONVERSIONS.lock").exists();
afCopied = existsAFVer && existsAFApp && (existsAFPostT || existsAFPostC);
}
if (notAD) {
adCopied = true;
} else {
boolean existsADVer = new File("/data/data/" + packageName + "/ADVERSION.lock").exists();
boolean existsADApp = new File("/data/data/" + packageName + "/ADAPP.lock").exists();
adCopied = existsADVer && existsADApp;
}
Thread.sleep(2000);
}
while (System.currentTimeMillis() - begin <= minSecondOfWait * 1000){ Thread.sleep(2000); }
printWriter.println("cp -a /data/data/" + packageName + "/AFVERSION.txt /data/data/com.bytedance.ttcollector/" + packageName + "/AFVERSION.txt");
printWriter.println("cp -a /data/data/" + packageName + "/AFAPP.txt /data/data/com.bytedance.ttcollector/" + packageName + "/AFAPP.txt");
printWriter.println("cp -a /data/data/" + packageName + "/AFT.txt /data/data/com.bytedance.ttcollector/" + packageName + "/AFT.txt");
printWriter.println("cp -a /data/data/" + packageName + "/AFCONVERSIONS.txt /data/data/com.bytedance.ttcollector/" + packageName + "/AFCONVERSIONS.txt");
printWriter.println("cp -a /data/data/" + packageName + "/AFREQUEST.txt /data/data/com.bytedance.ttcollector/" + packageName + "/AFREQUEST.txt");
printWriter.println("cp -a /data/data/" + packageName + "/ADVERSION.txt /data/data/com.bytedance.ttcollector/" + packageName + "/ADVERSION.txt");
printWriter.println("cp -a /data/data/" + packageName + "/ADAPP.txt /data/data/com.bytedance.ttcollector/" + packageName + "/ADAPP.txt");
printWriter.println("chmod 777 /data/data/com.bytedance.ttcollector/" + packageName + "/*.*");
printWriter.flush();
printWriter.close();
return returnResult(process.waitFor());
}
private Pair<String, String> readSdkVer(String packageName, String verFileName, String appFileName, String nameIfExists){
Pair<String, String> result = new Pair("unknown", "unknown");
try {
File fVer = new File("/data/data/com.bytedance.ttcollector/" + packageName, verFileName);
if (fVer.exists()){
File fApp = new File("/data/data/com.bytedance.ttcollector/" + packageName, appFileName);
BufferedReader readerVer = new BufferedReader(new InputStreamReader(new FileInputStream(fVer)));
String thirdDetect = fApp.exists() ? nameIfExists : (nameIfExists + "2");
String thirdVer = readerVer.readLine();
readerVer.close();
result = new Pair<>(thirdDetect, thirdVer);
}
}catch (Throwable e){ }
return result;
}
private Pair<String, String> saveInfoOfApkVer(String packageName, String fileName, Pair<String, String> afver, Pair<String, String> adver){
String thirdDetect = "unknown", thirdVer = "unknown";
try {
if (!afver.first.equals("unknown") && !adver.first.equals("unknown")) {
thirdDetect = afver.first + "+" + adver.first;
thirdVer = afver.second + "+" + adver.second;
}else if(!afver.first.equals("unknown") || !adver.first.equals("unknown")) {
if(afver.first.equals("unknown")) {
thirdDetect = adver.first;
thirdVer = adver.second;
} else {
thirdDetect = afver.first;
thirdVer = afver.second;
}
}
String sql = "UPDATE apkinfo1 SET ThirdDetect = '" + thirdDetect + "', ThirdVer = '" + thirdVer + "' WHERE PackageName = '" + packageName + "' AND ApkPath = '" + fileName + "'";
_dbStat.execute(sql);
} catch(Throwable e){
e.printStackTrace();
}
return new Pair<>(thirdDetect, thirdVer);
}
private String addAFOption(String packageName, String latestVerOption, String json, String postFile){
String result = "";
try {
JSONObject target = new JSONObject(json);
FileReader fileReader = new FileReader(postFile);
BufferedReader reader = new BufferedReader(fileReader);
JSONObject option = new JSONObject();
JSONObject post = new JSONObject(reader.readLine());
if (post.has("android_id")){
String android_id = "", current_value = post.getString("android_id");
try { android_id = Settings.Secure.getString(_context.getContentResolver(), Settings.Secure.ANDROID_ID); }catch (Throwable ex){}
if (android_id != null && !android_id.isEmpty()) {
current_value = current_value.replace(android_id, "{android_id}");
}
if (post.has("advertiserId")){
String advertiserId = post.getString("advertiserId");
current_value = current_value.replace(advertiserId, "{gaid}");
}
if (post.has("uid")){
String uid = post.getString("uid");
current_value = current_value.replace(uid, "{uid}");
}
if(!current_value.contains("{")){
option.put("manualhandle", true);
}
option.put("android_id", current_value);
}
if (post.has("appUserId")){
String android_id = "", current_value = post.getString("appUserId");
try { android_id = Settings.Secure.getString(_context.getContentResolver(), Settings.Secure.ANDROID_ID); }catch (Throwable ex){}
if (android_id != null && !android_id.isEmpty()) {
current_value = current_value.replace(android_id, "{android_id}");
}
if (post.has("advertiserId")){
String advertiserId = post.getString("advertiserId");
current_value = current_value.replace(advertiserId, "{gaid}");
}
if (post.has("uid")){
String uid = post.getString("uid");
current_value = current_value.replace(uid, "{uid}");
}
if(!current_value.contains("{")){
option.put("manualhandle", true);
}
option.put("appUserId", current_value);
}
if (post.has("customData")){
String android_id = "", current_value = post.getString("customData");
try { android_id = Settings.Secure.getString(_context.getContentResolver(), Settings.Secure.ANDROID_ID); }catch (Throwable ex){}
if (android_id != null && !android_id.isEmpty()) {
current_value = current_value.replace(android_id, "{android_id}");
}
if (post.has("advertiserId")){
String advertiserId = post.getString("advertiserId");
current_value = current_value.replace(advertiserId, "{gaid}");
}
if(!current_value.contains("{")){
option.put("manualhandle", true);
}
option.put("customData", current_value);
}
if (post.has("currency")){
option.put("currency", post.getString("currency"));
}
if (post.has("onelink_id")){
option.put("onelink_id", post.getString("onelink_id"));
}
if (post.has("af_currentstore")){
option.put("api_store_value", post.getString("af_currentstore"));
}
// if (post.has("channel")){
// option.put("channel", post.getString("channel"));
// }
// if (post.has("imei")){
// option.put("imei", post.getString("imei"));
// }
// if (post.has("lvl")){
// option.put("lvl", true);
// }
//比对
if (latestVerOption != null && latestVerOption.length() != 0) {
JSONObject latestVerOptionJson = new JSONObject(latestVerOption);
Iterator<String> it = latestVerOptionJson.keys();
while (it.hasNext()) {
String key = it.next();
// Log.d(TAG, "propCorrection: key " + key);
// Log.d(TAG, "propCorrection: value " + prop4ServerJson.getString(key));
//信任服务器旧版数据模式
// if ((!option.has(key)) || option.getString(key).equals("")) {
// //propJson.put(key, prop4ServerJson.getString(key));
// option.put(key, latestVerOptionJson.get(key));
// }
//信任自己取到的数据模式
if ((option.has(key))) {
option.remove(key);
option.put(key, latestVerOptionJson.get(key));
}
}
}
if (option.length() > 0) {
//替换uuid android_id gaid
String optionStr = option.toString();
optionStr = optionStr.replaceAll("[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}", "{uuid36}");
optionStr = optionStr.replaceAll("[0-9A-F]{8}(-[0-9A-F]{4}){3}-[0-9A-F]{12}", "{uuid36U}");
optionStr = optionStr.replaceAll("[0-9a-f]{32}", "{uuid32}");
optionStr = optionStr.replaceAll("[0-9A-F]{32}", "{uuid32U}");
optionStr = optionStr.replaceAll("[0-9a-fA-F]{16}", "{android_id}");
//额外需要修改参数的apk判断
optionStr = specOption(packageName, optionStr);
option = new JSONObject(optionStr);
//prop.put("option", option);
target.put("option", option);
}
result = target.toString();
reader.close();
fileReader.close();
}catch (Throwable e){
e.printStackTrace();
}
return result;
}
//特殊APP的option处理
public static String specOption(String packageName, String optionStr) {
String specPackageNames = "com.eterno.shortvideos|com.fiverr.fiverr";
if (specPackageNames.contains(packageName)) {
JSONObject prop = null;
try {
prop = new JSONObject(optionStr);
if (prop == null) return optionStr;
switch (packageName) {
case "com.eterno.shortvideos":
if (prop.has("appUserId")) {
prop.put("appUserId", "j.{2}{0}{2}{1}{2}{1}{1}{1}{2}{1}{1}{1}{2}{2}{2}{1}{1}{1}{2}{1}{2}{1}{2}{2}{2}{0}{2}{2}{2}{1}09A");
}
break;
case "com.fiverr.fiverr":
if (prop.has("appUserId")) {
prop.put("appUserId", "{timestamp13}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}");
}
break;
case "com.neptune.domino":
if (prop.has("appUserId")) {
prop.put("appUserId", "{4}{4}:{4}{4}:{4}{4}:{4}{4}:{4}{4}:{4}{4}");
}
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
optionStr = prop.toString();
}
return optionStr;
}
private JSONArray getRequestEvents(String packageName){
JSONArray subEvents = new JSONArray();
try{
File fRequest = new File("/data/data/com.bytedance.ttcollector/" + packageName, "AFREQUEST.txt");
if (fRequest.exists()){
BufferedReader readerApp = new BufferedReader(new InputStreamReader(new FileInputStream(fRequest)));
List<Long> timestamps = new ArrayList<>();
HashMap<Long, JSONObject> map = new HashMap<>();
String line = readerApp.readLine();
while (line != null){
try{
if (!line.isEmpty()){
JSONObject request = new JSONObject(line);
long timestamp = request.getLong("timestamp");
String url = request.getString("url");
if (!url.contains("t.appsflyer.com") && !url.contains("conversions.appsflyer.com")){
map.put(timestamp, request);
timestamps.add(timestamp);
}
}
line = readerApp.readLine();
}catch (Exception ex){
line = "";
}
}
Collections.sort(timestamps);
for (int i = 0; i < timestamps.size(); i++) {
String type = "", name = "", value = "";
long timeDelayMin = 100, timeDelayMax = 100;
try{
JSONObject target = map.get(timestamps.get(i));
JSONObject targetContent = new JSONObject(target.getString("content"));
URL url = new URL(target.getString("url"));
String host = url.getHost();
if (host.equals("attr.appsflyer.com")){ type = "attr"; }
else if (host.equals("register.appsflyer.com")){ type = "register"; }
else if (host.equals("launches.appsflyer.com")){ type = "launche"; }
else if (host.equals("inapps.appsflyer.com")){
type = "inapp";
name = targetContent.getString("eventName");
value = targetContent.getString("eventValue");
}
if (i < (timestamps.size() - 1)){
timeDelayMin = timestamps.get(i + 1) - timestamps.get(i) - 2;
timeDelayMax = timestamps.get(i + 1) - timestamps.get(i) + 2;
}
JSONObject subEventsItem = new JSONObject();
subEventsItem.put("type", type);
subEventsItem.put("name", name);
subEventsItem.put("value", value);
subEventsItem.put("timeDelayMin", timeDelayMin);
subEventsItem.put("timeDelayMax", timeDelayMax);
subEvents.put(subEventsItem);
}catch (Exception ex){
}
}
}
}catch (Throwable err){
err.printStackTrace();
}
return subEvents;
}
private void saveInfoOfApkAFInfo(String packageName, String fileVer, String afVer){
try {
File fApp = new File("/data/data/com.bytedance.ttcollector/" + packageName, "AFAPP.txt");
File fPostT = new File("/data/data/com.bytedance.ttcollector/" + packageName, "AFT.txt");
File fPostC = new File("/data/data/com.bytedance.ttcollector/" + packageName, "AFCONVERSIONS.txt");
if (fApp.exists()){
BufferedReader readerApp = new BufferedReader(new InputStreamReader(new FileInputStream(fApp)));
String dataContent = readerApp.readLine();
readerApp.close();
if (fPostT.exists() || fPostC.exists()){
//从服务器读取参数
String latestVerOption = queryLatestProp(packageName);
dataContent = addAFOption(packageName, latestVerOption, dataContent, fPostC.exists() ? fPostC.getPath() : fPostT.getPath());
}
String sql = "INSERT INTO apkprotocprop (PackageName, Prop, appVer, thirdParty, thirdVer) VALUES(?, ?, ?, ?, ?);";
// PreparedStatement ps = _dbConn.prepareStatement(sql);
// ps.setString(1, packageName);
// ps.setString(2, dataContent);
// ps.setString(3, fileVer);
// ps.setString(4, "AF");
// ps.setString(5, afVer);
// ps.executeUpdate();
// Log.e("AFTask", "apkprotocprop update ok");
// String url = String.format("http://123.56.44.45/tt/manage/apkInfo!addApkProtocPropOp.do?apkProtocProp.packageName=%s&apkProtocProp.appVer=%s&apkProtocProp.thirdParty=%s&apkProtocProp.thirdVer=%s&apkProtocProp.prop=%s", packageName, fileVer, "AF", afVer, dataContent);
// System.out.println(url);
OkHttpClient client = new OkHttpClient();
FormBody formBody = null;
JSONObject jsonObject = new JSONObject(dataContent);
formBody = new FormBody.Builder()
.add("apkProtocProp.packageName", packageName)
.add("apkProtocProp.appVer", fileVer)
.add("apkProtocProp.thirdParty", "AF")
.add("apkProtocProp.thirdVer", afVer)
.add("apkProtocProp.prop", jsonObject.toString())
.build();
Request request = new Request.Builder()
.url("http://123.56.44.45/tt/manage/apkInfo!addApkProtocPropOp.do?")
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.method("POST", formBody)
.build();
Response response = client.newCall(request).execute();
if(response.code() == 200) {
System.out.println("UpdateOK");
}
else {
System.out.println("UpdateError");
}
}
}catch (IOException | JSONException e){
e.printStackTrace();
}
}
private String queryLatestProp(String packageName) {
String propString = null;
int latestVersionCode = 0;
String optionString = null;
String sql = "SELECT * FROM apkprotocprop WHERE PackageName = ?;";
try {
PreparedStatement ps = _dbConn.prepareStatement(sql);
ps.setString(1, packageName);
ResultSet rs = ps.executeQuery();
while (rs.next()){
propString = rs.getString("Prop");
JSONObject jsonObject = new JSONObject(propString);
if (jsonObject.has("versionCode")){
if (jsonObject.getInt("versionCode") > latestVersionCode){
latestVersionCode = jsonObject.getInt("versionCode");
if (jsonObject.has("option")){
optionString = jsonObject.getString("option");
}
}
}
}
Log.d("AFTask", "queryLatestProp: " + propString);
} catch (SQLException | JSONException e) {
e.printStackTrace();
}
Log.e("AFTask", "latestVersionCode: " + latestVersionCode + " option: " + optionString);
return optionString;
}
private void saveInfoOfApkADInfo(String packageName, String fileVer, String adVer){
try {
File fApp = new File("/data/data/com.bytedance.ttcollector/" + packageName, "ADAPP.txt");
if (fApp.exists()){
BufferedReader readerApp = new BufferedReader(new InputStreamReader(new FileInputStream(fApp)));
String dataContent = readerApp.readLine();
readerApp.close();
String sql = "INSERT INTO apkprotocprop (PackageName, Prop, appVer, thirdParty, thirdVer) VALUES(?, ?, ?, ?, ?);";
// PreparedStatement ps = _dbConn.prepareStatement(sql);
// ps.setString(1, packageName);
// ps.setString(2, dataContent);
// ps.setString(3, fileVer);
// ps.setString(4, "ADJUST");
// ps.setString(5, adVer);
// ps.executeUpdate();
// Log.e("AFTask", "apkprotocprop update ok");
// String url = String.format("http://123.56.44.45/tt/manage/apkInfo!addApkProtocPropOp.do?apkProtocProp.packageName=%s&apkProtocProp.appVer=%s&apkProtocProp.thirdParty=%s&apkProtocProp.thirdVer=%s&apkProtocProp.prop=%s", packageName, fileVer, "ADJUST", adVer, dataContent);
// System.out.println(url);
OkHttpClient client = new OkHttpClient();
FormBody formBody = null;
JSONObject jsonObject = new JSONObject(dataContent);
formBody = new FormBody.Builder()
.add("apkProtocProp.packageName", packageName)
.add("apkProtocProp.appVer", fileVer)
.add("apkProtocProp.thirdParty", "ADJUST")
.add("apkProtocProp.thirdVer", adVer)
.add("apkProtocProp.prop", jsonObject.toString())
.build();
Request request = new Request.Builder()
.url("http://123.56.44.45/tt/manage/apkInfo!addApkProtocPropOp.do?")
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.method("POST", formBody)
.build();
Response response = client.newCall(request).execute();
if(response.code() == 200) {
System.out.println("UpdateOK");
}
else {
System.out.println("UpdateError");
}
}
}catch (IOException | JSONException e){
e.printStackTrace();
}
}
private void updateEventOfApk(String packageName, String fileName){
JSONObject eventJson = new JSONObject();
try{
eventJson.put("afterInstallSync", true);
eventJson.put("afterInstallDelayMin", 3);
eventJson.put("afterInstallDelayMax", 10);
eventJson.put("sysVars", new JSONObject());
JSONArray events = new JSONArray();
JSONObject eventsItem = new JSONObject();
eventsItem.put("sort", 1);
eventsItem.put("subEvents", getRequestEvents(packageName));
events.put(eventsItem);
eventJson.put("events", events);
String sql = "UPDATE apkinfo1 SET eventJson = ? WHERE PackageName = ? AND ApkPath = ?";
PreparedStatement ps = _dbConn.prepareStatement(sql);
ps.setString(1, eventJson.toString());
ps.setString(2, packageName);
ps.setString(3, fileName);
ps.executeUpdate();
}catch (Exception err){
err.printStackTrace();
}
}
/**
* 保存参数到数据库
* @param packageName
* @param fileName
* @return
* @throws Throwable
*/
private void saveInfoOfApk(String packageName, String fileName) {
String fileVer = fileName.substring(fileName.lastIndexOf("_") + 1, fileName.lastIndexOf("."));
Pair<String, String> afver = readSdkVer(packageName, "AFVERSION.txt", "AFAPP.txt", "appsflyer");
Pair<String, String> adver = readSdkVer(packageName, "ADVERSION.txt", "ADAPP.txt", "adjust");
saveInfoOfApkVer(packageName, fileName, afver, adver);
saveInfoOfApkAFInfo(packageName, fileVer, afver.second);
saveInfoOfApkADInfo(packageName, fileVer, adver.second);
updateEventOfApk(packageName, fileName);
}
private void saveApp(String appid, String fileName, long waitMaxSecond, long waitMinSecond){
try{
if (copyLogFile(appid, waitMaxSecond, waitMinSecond)){
saveInfoOfApk(appid, fileName);
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private void doBusiness(String apkPath, long waitMaxSecond, long waitMinSecond) throws Throwable{
String fileName = "";
if(apkPath != ""){
fileName = apkPath;
}else {
fileName = apkFileName(_appid);
}
String path = downloadAPK(_downloadUrl, fileName);
Log.e("AFTask", "Download apk end");
//移动到tmp文件夹
CmdUtils.moveFile2Tmp(path);
String apkSdcard = path;
path = "/data/local/tmp/" + fileName;
if(path.endsWith(".apk")) {
clientInstallApk(new File(path));
} else {
clientInstallApks(new File(path));
}
Log.e("AFTask", "install apk end");
// deleteAPK(path);
deleteAPK(apkSdcard);
CmdUtils.deleteFile(path);
if (openApp(_appid)){
Log.e("AFTask", "open apk end");
saveApp(_appid, fileName, waitMaxSecond, waitMinSecond);
}
clientUninstall(_appid);
}
// /**
// * 初始化
// * @throws Throwablel
// */
public void init(String dbhost, String dbname, String dbuser, String dbpass) throws Throwable {
Class.forName("com.mysql.jdbc.Driver");
_dbConn= DriverManager.getConnection("jdbc:mysql://" + dbhost + "/" + dbname, dbuser, dbpass);
_dbStat = (Statement)_dbConn.createStatement();
}
public void start(long waitMaxSecond, long waitMinSecond){
new Thread(new Runnable(){
@Override
public void run() {
try{
doBusiness("", waitMaxSecond, waitMinSecond);
}catch (Throwable err){
XposedBridge.log("AFTASK ERROR : " + err.getMessage());
}
}
}).start();
}
public static void startTask(Context context){
new Thread(new Runnable(){
@Override
public void run() {
while(!_paused){
String packageName = "", apkPath = "";
int code = -1;
try {
HttpURLConnection conn = (HttpURLConnection) new URL("http://123.56.44.45/tt/ddj/autoApk.do").openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if (200 == conn.getResponseCode()){
String line;
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = br.readLine()) != null) {
sb.append(line);
}
Log.e("AFTask", sb.toString());
JSONObject json = new JSONObject(sb.toString());
if (go)
{
json = new JSONObject("{\"code\":1,\"apkPath\":\"com.jar.app_4.9.6.apk\",\"packageName\":\"com.jar.app\"}");
go = false;
}
//JSONObject json = new JSONObject("{\"code\":1,\"apkPath\":\"ru.ligastavok.android_3.8.0.apk\",\"packageName\":\"ru.ligastavok.android\"}");
code = json.has("code") ? json.getInt("code"): -1;
packageName = json.has("packageName") ? json.getString("packageName") : "";
apkPath = json.has("apkPath") ? json.getString("apkPath") : "";
}
if (code != 1) {
Thread.sleep(5000);
continue;
}
//if (code != 1) { continue; }
if (packageName == null || apkPath == null) { continue; }
if (packageName.isEmpty() || apkPath.isEmpty()) { continue; }
//TTTask task = new TTTask(context, packageName, "http://123.56.44.45/tt/upload/ddj/");
TTTask task = new TTTask(context, packageName, "http://39.103.73.250/tt/upload/ddj/");
task.init("pc-2ze3t9ojzloi45k3to.mysql.polardb.rds.aliyuncs.com", "advert_lcddj", "advertuser1116", "IvM@ck#z9$Eqy3KGBK4g");
task.doBusiness(apkPath, 60, 0);
Log.e("AFTask", "Loop end for pack: " + packageName);
} catch(Throwable e){
Log.d("AFTask", "run: " + e.toString());
e.printStackTrace();
}
}
}
}).start();
}
}