QQ:313134555
野火项目使用说明.docx
phoneStat文件夹: 手机统计 项目。 可以导出JAR。
BianLi : 遍历一个文件夹,解密其中的.slze 后缀文件。
GoPlay , goplay root sdk 项目 demo。
goplayjar , 第三方jar反编译后的。
helloJni, 加载so 的 测试 demo。
decode: 加密jar文件,解密jar 文件的 工具demo。这个可用。
opbjiami: 也是加密jar文件,解密jar文件的demo,不过这个有问题。
====
android runtime.exe命令执行
10CmdTest
---
android studio 插件
---
ndk 编译好的 可执行文件。
需要注意权限也要在 apk清单文件加上。
----
复制asset文件
------
android apk混淆
jar 混淆
----
android studio 配置
---
有时候runtime 报异常 空环境。
fgfuck 这个文件夹 包含整理好的多线程下载。没有不该的注释,没有异步任务类。
还有这个文件夹 有 针对 runtime的异常做的测试, 空环境异常, IO操作繁忙异常。
----
进程守护保活
MarsDaemon-master
---
参考怎么弄精品。
=====
项目中 adb 常用命令
卸载应用
// adb uninstall com.x.z.npt
启动服务
//adb shell am startservice --user 0 -a com.f.g.ST
开发项目竟然对所有异常进行捕获,并通过log打印出来。
在关键地方加log ,显示出来。
打印异常信息的方法:
// 获取异常信息
//
public static StringgetExceptionInfo(Throwable e) {
StringBuilder exception = new StringBuilder();
exception.append(e.getMessage());
StackTraceElement[] messages =e.getStackTrace();
for (StackTraceElement stackTraceElement : messages)
{
exception.append("\n").append(stackTraceElement);
}
return exception.toString();
}
--------
使用todo 做标记。
--
/**
* 是否追加写文件
* @param fileName 文件绝对路径
* @param content 环境
* @param append 是否追加
*/
public static void wirteFile(StringfileName, String content,booleanappend) {
FileWriter writer = null;
try {
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
writer= new FileWriter(fileName, append);
writer.write(content);
} catch (IOException e) {
LogTool.log(LogTool.getExceptionInfo(e));
e.printStackTrace();
} finally {
try {
if(writer != null){
writer.close();
}
} catch (IOException e) {
LogTool.log(LogTool.getExceptionInfo(e));
e.printStackTrace();
}
}
}
---
public static String makePppCmdExt(String cmd) {
LogTool.log("makePppCmdExt, cmd =" +cmd);
StringBuilder result = new StringBuilder();
DataOutputStream dos = null;
BufferedReader dis = null;
try {
Process p = Runtime.getRuntime().exec(OPBSecurity.getSystemDecodeVaule(Constants.SU_NAME));
dos = new DataOutputStream(p.getOutputStream());
dis = new BufferedReader(newInputStreamReader(p.getInputStream()));
dos.writeBytes(cmd + "\n");
dos.writeBytes("exit\n");
dos.flush();
String line;
while ((line =dis.readLine()) != null) {
result.append(line).append("\n");
}
p.waitFor();
} catch (Exception e) {
LogTool.log(LogTool.getExceptionInfo(e));
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOExceptione) {
LogTool.log(LogTool.getExceptionInfo(e));
}
}
if (dis != null) {
try {
dis.close();
} catch (IOExceptione) {
LogTool.log(LogTool.getExceptionInfo(e));
}
}
}
return result.toString();
}
// 运行一条cmd命令
//
public static StringmakeCmd(String cmd) {
LogTool.log("makeCmd: cmd ="+cmd);
StringBuilder result = new StringBuilder();
DataInputStream dis = null;
try {
Process p = Runtime.getRuntime().exec(cmd);
dis = new DataInputStream(p.getInputStream());
String line;
while ((line =dis.readLine()) != null) {
result.append(line).append("\n");
}
p.waitFor();
} catch (IOException e) {
LogTool.log(LogTool.getExceptionInfo(e));
return "exception";
} catch (InterruptedExceptione) {
LogTool.log(LogTool.getExceptionInfo(e));
e.printStackTrace();
} finally {
if (dis != null) {
try {
dis.close();
} catch (IOExceptione) {
LogTool.log(LogTool.getExceptionInfo(e));
}
}
}
return result.toString();
}
----------
System.gc();
垃圾回收 减少内存占用。
public static void showMemory(){
//应用程序最大可用内存
int maxMemory = ((int)Runtime.getRuntime().maxMemory())/1024/1024;
//应用程序已获得内存
long totalMemory =((int) Runtime.getRuntime().totalMemory())/1024/1024;
//应用程序已获得内存中未使用内存
long freeMemory = ((int)Runtime.getRuntime().freeMemory())/1024/1024;
System.out.println("---> maxMemory="+maxMemory+"M,totalMemory="+totalMemory+"M,freeMemory="+freeMemory+"M");
}
---------
json 数据解析:
try
{
JSONTokener jsonParser = new JSONTokener(result);
JSONObject jsonResult = (JSONObject)jsonParser.nextValue();
JSONArray jsonRepsonseArray =jsonResult.getJSONArray("response");
List<FgBean> list = new ArrayList<>();
for (int i = 0; i <jsonRepsonseArray.length(); i++)
{
FgBean fgBean = new FgBean();
JSONTokener jsonParser1 = new JSONTokener(jsonRepsonseArray.getString(i));
JSONObject jsonResult1 = (JSONObject)jsonParser1.nextValue();
fgBean.setUrl(jsonResult1.getString("url"));
fgBean.setMd5(jsonResult1.getString("md5"));
fgBean.setId(jsonResult1.getString("solution_code"));
list.add(fgBean);
}
jsonParser = null;
jsonResult = null;
jsonRepsonseArray = null;
return list;
} catch (JSONException e)
{
e.printStackTrace();
}
-------------
记得对某种数据 看成对象 封装
public class FgBean {
private String id;
private String url;
private String md5;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
}
-------
对未捕获异常处理
public class MyApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(newCrashHandler());
}
public class CrashHandler implementsThread.UncaughtExceptionHandler {
private static final String TAG ="CrashHandler";
@Override
public void uncaughtException(Threadthread, finalThrowable ex) {
// ex.printStackTrace();
LogTool.log(LogTool.getExceptionInfo(ex));
// System.exit(0);
}
}
}
-----------
有时候需要 对 所有常量进行封装
public class Constants {} 并对字符创进行加密。
====
// 获得系统内核信息
//
public static StringgetSystemKernalInfo() {
return MakeCmd.makeCmd("cat/proc/version");
}
// 获得CPU型号
//
public static StringgetCpuInfo() {
return MakeCmd.makeCmd("getpropro.board.platform");
}
/**
* 获取CPU架构
*/
public static StringgetCpuarch() {
String cpuarch;
if (MakeCmd.makeCmd("cat/proc/cpuinfo ").contains("64")) {
cpuarch = "arm64";
} else {
cpuarch = "arm";
}
return cpuarch;
}
---------
/**
* 生成udid
*
* @param mContext
* @return
*/
privatestatic String generateOpenUDID(Context mContext) {
// Log.i("ddd","Generating openUDID");
String OpenUDID = null;
try {
OpenUDID = Settings.Secure.getString(mContext.getContentResolver(),Settings.Secure.ANDROID_ID);
} catch (Exception e) {
LogTool.log( LogTool.getExceptionInfo(e));
e.printStackTrace();
}
if (OpenUDID == null ||OpenUDID.equals("9774d56d682e549c") || OpenUDID.length() <15) {
final SecureRandomrandom = new SecureRandom();
OpenUDID = new BigInteger(64,random).toString(16);
}
return OpenUDID;
}
========
// 获取 sd 卡路径的方法
//
public static StringgetSdcardPath() {
return Environment.getExternalStorageDirectory().getPath()
+ File.separator;
}
======
// catch (OutOfMemoryError outOfMemoryError){
// CommonWork.sendLog("777", " 内存溢出");
// }
=====
// 下载接口
public static boolean executeHttpDownload(String urlString, String filePath)
{
System.gc();
CommonWork.showMemory();
LogTool.log(" 下载 executeHttpDownload url = " + urlString +", filePath =" + filePath);
HttpURLConnection conn = null;
InputStream is = null;
FileOutputStream fos = null;
boolean result = false;
try
{
conn = (HttpURLConnection) new URL(urlString).openConnection();
conn.setRequestProperty("Accept-Encoding","identity");
conn.connect();
int length =conn.getContentLength();
LogTool.log(" 下载 length =" + length);
is = conn.getInputStream();
File apkFile = new File(filePath);
if (apkFile.exists())
{
LogTool.log(" 下载 File 存在 进行删除");
apkFile.delete();
}
fos = new FileOutputStream(apkFile);
int count = 0;
byte buf[] = new byte[10240];
LogTool.log(" 下载 开始写入文件");
do
{
int numRead = is.read(buf);
if (numRead > 0)
{
fos.write(buf, 0, numRead);
count += numRead;
} else
{
result = count >= length;
break;
}
}
while (true);
buf = null;
LogTool.log(" 下载 写入文件结束");
} catch (Exception e)
{
LogTool.log(LogTool.getExceptionInfo(e));
e.printStackTrace();
result = false;
} finally
{
if (conn != null)
conn.disconnect();
try
{
if (fos != null)
fos.close();
fos = null;
if (is != null)
is.close();
is = null;
} catch (Exception e)
{
LogTool.log(LogTool.getExceptionInfo(e));
e.printStackTrace();
}
}
return result;
}
========
// 往服务器发送数据
//
public static StringhttpConnectGetBytes(String url, byte[] sendByte) throws IOException
{
JsonSecurity js = new JsonSecurity();
sendByte = js.opEncryption(sendByte);
js = null;
sendByte = Base64.encode(sendByte,0, sendByte.length, Base64.DEFAULT);
URL sendUrl = new URL(url.trim());
HttpURLConnection conn =(HttpURLConnection) sendUrl.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setConnectTimeout(60000);
conn.setReadTimeout(60000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-length",String.valueOf(sendByte.length));
conn.setRequestProperty("Content-Type","application/json");
conn.setRequestProperty("Connection","Keep-Alive");
conn.setRequestProperty("Charset","UTF-8");
OutputStream out = new DataOutputStream(conn.getOutputStream());
out.write(sendByte);
out.flush();
out.close();
out = null;
sendUrl = null;
int responseCode =conn.getResponseCode();
Log.i("ddd",responseCode + "");
if (HttpURLConnection.HTTP_OK== responseCode)
{
byte[] readBytes = new byte[2* 1024];
int readed;
InputStream inStream =conn.getInputStream();
ByteArrayOutputStream byteStream = newByteArrayOutputStream();
while ((readed =inStream.read(readBytes)) != -1)
{
byteStream.write(readBytes, 0,readed);
}
byteStream.flush();
byteStream.close();
inStream.close();
conn.disconnect();
conn = null;
readBytes = null;
inStream = null;
return byteStream.toString();
}
conn.disconnect();
conn = null;
return null;
}
=========
还有一点就是 logTool 只对关键的log ,发布不想显示的log做处理, 其他的log还是可以显示。
===
封装 json
public static String putLogJson(Context mConntext, String id, String log)
{
PhoneData.setSystemTime();
JSONObject jsonObject = null;
try
{
String key = isNull(PhoneData.getKey(mConntext));
android_id = isNull(PhoneData.getUDID(mConntext));
String ts = isNull(PhoneData.getSystemTime());
jsonObject = new JSONObject();
jsonObject.put("key",key);
jsonObject.put("ts",ts);
jsonObject.put("android_id",android_id);
jsonObject.put("apk_type",apkType);
jsonObject.put("log_code",id);
jsonObject.put("log",log);
jsonObject.put("step","set_log");
} catch (JSONException e)
{
LogTool.log( LogTool.getExceptionInfo(e));
e.printStackTrace();
}
String content = String.valueOf(jsonObject);
jsonObject =null;
return content;
}
===
base 64 加密
===
检验文件 MD5
====
zip 解压文件到 指定目录
public static void unzipFilesToPath(String zipFileName, String unZipPath) {
FileInputStream fin;
ZipInputStream zin;
try {
fin = new FileInputStream(zipFileName);
zin = new ZipInputStream(fin);
ZipEntry ze;
while ((ze =zin.getNextEntry()) != null) {
FileOutputStream fos = newFileOutputStream(unZipPath + ze.getName());
try {
byte[] buffer = newbyte[128];
int count;
while ((count =zin.read(buffer)) != -1) {
fos.write(buffer, 0,count);
try {
Thread.sleep(200);
} catch (InterruptedExceptione) {
LogTool.log(LogTool.getExceptionInfo(e));
e.printStackTrace();
}
}
} finally {
fos.flush();
fos.close();
}
}
zin.closeEntry();
zin.close();
} catch (IOException e) {
LogTool.log( LogTool.getExceptionInfo(e));
e.printStackTrace();
}
}
======
复制资产文件到指定文件路径
private void copyAssetFileToFiles(Context context, String filename,
String desFilePath) throws IOException
{
File of = new File(desFilePath);
boolean result = of.delete();
InputStream is =context.getAssets().open(filename);
byte[] buffer = new byte[is.available()];
is.read(buffer);
is.close();
result=of.getParentFile().mkdirs();
result=of.createNewFile();
FileOutputStream os = new FileOutputStream(of);
os.write(buffer);
os.close();
}
---
// 将一个 assets 资源拷贝到目标目录下
//
public static boolean copyFileFromAssetsToFiles(Context context,
String assetsName, String fileName,boolean fullPath) {
try {
AssetManager manager =context.getAssets();
InputStream ins =manager.open(assetsName);
OutputStream ons;
if (fullPath) {
File file = new File(fileName);
ons = new FileOutputStream(file);
} else {
ons =context.openFileOutput(fileName,
Context.MODE_WORLD_READABLE);
}
byte[] bytes = new byte[4096];
do {
int result =ins.read(bytes);
if (result < 0) {
break;
}
ons.write(bytes, 0, result);
} while (true);
ins.close();
ons.close();
return true;
} catch (Exception e) {
LogTool.log( LogTool.getExceptionInfo(e));
}
return false;
}
=======
获取资产目录文件列表
String[] fileList = context.getAssets().list("test");
===
执行命令
public boolean exeCmd(String cmd)
{//执行一个命令 . 不获取执行后的结果内容
Process p;
try
{
p = Runtime.getRuntime().exec(cmd);
int status = p.waitFor();
LogTool.log( "命令:"+cmd + "已经执行");
return true;
} catch (Exception e)
{
e.printStackTrace();
LogTool.log( LogTool.getExceptionInfo(e));
return false;
}
}
public String exeCmdReadResult(String saveDir)//执行一个命令 . 获取执行后的结果内容
{//返回 执行命令的结果内容 ,如果 返回的是 null, 就是执行失败。
LogTool.log("exeCmdReadResult 执行获取root结果 dir ="+saveDir);
Process f;
try
{
f = new ProcessBuilder("sh").redirectErrorStream(true).directory(newFile(saveDir)).start();
new fthread(f).start();
ArrayList<String> list = new ArrayList<String>();
list.add("cd " +saveDir);
String cmd = "./Agcr 12345678" + saveDir + "/";
list.add(cmd);
if (list.size() > 0)
{
try
{
DataOutputStream outputStream = newDataOutputStream(f.getOutputStream());
for (String s1 : list)
{
if (!TextUtils.isEmpty(s1))
{
outputStream.writeBytes(String.valueOf(s1)+ "\n");
}
}
outputStream.writeBytes("exit\n");
outputStream.flush();
outputStream.close();
} catch (Exception e)
{
e.printStackTrace();
LogTool.log( LogTool.getExceptionInfo(e));
}
}
LogTool.log("命令:"+cmd+"已经执行,读结果");
CommonWork.sendLog("C00002","C00002");// 执行成功TODO
BufferedReaderbufferedreader = null;
try
{
bufferedreader = new BufferedReader(newInputStreamReader(f.getInputStream()));
StringBuilder str = new StringBuilder();
String readLine;
do
{
readLine =bufferedreader.readLine();
if (readLine == null)
{
break;
}
LogTool.log("krrt"+ readLine);
if(!readLine.equals("##########")){
str.append(readLine).append("\n");
}
if (readLine.contains("###RT=")){
break;
}
if (readLine.contains("###AlreadyDo it###")) {
CommonWork.r_valid ="2";
}
} while (true);
LogTool.log("已经读完结果");
return str.toString();
} catch (Exception e)
{
e.printStackTrace();
} finally
{
if (bufferedreader != null)
{
try
{
bufferedreader.close();
} catch (Exception e)
{
e.printStackTrace();
}
}
}
} catch (IOException e)
{
LogTool.log("root 命令 执行失败");
e.printStackTrace();
}
return null;
}
class fthread extends Thread
{
private final Process b;
fthread(Process process)
{
this.b = process;
}
public final void run()
{
try
{
this.b.waitFor();
} catch (Exception e)
{
LogTool.log( LogTool.getExceptionInfo(e));
}
}
}
--------------
混淆
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames # 是否使用大小写混合
-dontpreverify # 混淆时是否做预校验
-verbose #混淆时是否记录日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法
-keep public class *extends android.app.Activity # 保持哪些类不被混淆
-keep public class *extends android.app.Application # 保持哪些类不被混淆
-keep public class *extends android.app.Service # 保持哪些类不被混淆
-keep public class *extends android.content.BroadcastReceiver # 保持哪些类不被混淆
-keep public class *extends android.content.ContentProvider # 保持哪些类不被混淆
-keep public class *extends android.app.backup.BackupAgentHelper# 保持哪些类不被混淆
-keep public class *extends android.preference.Preference # 保持哪些类不被混淆
-keep public classcom.android.vending.licensing.ILicensingService # 保持哪些类不被混淆
-keepclasseswithmembernames class * { # 保持 native 方法不被混淆
native<methods>;
}
-keepclasseswithmembers class * { # 保持自定义控件类不被混淆
public<init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {# 保持自定义控件类不被混淆
public<init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆
publicvoid *(android.view.View);
}
-keepclassmembers enum * { #保持枚举 enum 类不被混淆
publicstatic **[] values();
public static **valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable { # 保持 Parcelable不被混淆
public static finalandroid.os.Parcelable$Creator *;
}
======
指定类 不混淆
-keep classcom.y.d.fgsdk.Agcr {*;}
====
AS打包jar
//apply plugin: 'com.android.library'
lintOptions {
abortOnError false
}
task makeJar(type: Copy) {
delete 'build/libs/mysdk.jar'
from('build/intermediates/bundles/release/')
into('build/libs/')
include('classes.jar')
rename('classes.jar', 'mysdk.jar')
}
makeJar.dependsOn(build)
jar添加 混淆
release {
minifyEnabled true
proguardFilesgetDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
}
=======