package com.aoleyun.sn.service; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; import com.aoleyun.sn.bean.BaseResponse; import com.aoleyun.sn.bean.SnRunLog; import com.aoleyun.sn.network.NetInterfaceManager; import com.aoleyun.sn.utils.Utils; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.schedulers.Schedulers; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.RequestBody; public class LogcatService extends Service { public final static String LOGCAT_START_ACTION = "START"; public final static String LOGCAT_STOP_ACTION = "STOP"; private String TAG = LogcatService.class.getSimpleName(); public LogcatService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. // throw new UnsupportedOperationException("Not yet implemented"); return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } @Override public void onCreate() { super.onCreate(); logFilePath = getExternalCacheDir() + File.separator + "LOG" + File.separator; File file = new File(logFilePath); if (!file.exists()) { file.mkdirs(); } // try { // exec = Runtime.getRuntime().exec(running); // final InputStream is = exec.getInputStream(); // logThread = new LogThread(is); // logThread.start(); // // is.close(); //// exec.destroy(); // } catch (IOException e) { //// e.printStackTrace(); // Log.e("第一个是Logcat", e.getMessage()); // } registerLogcatReceiver(); } private static long start_Time; private static long condition_duration; private static long condition_file_max_size; private static boolean clear_file; public static void setStart_Time(long start_Time) { LogcatService.start_Time = start_Time; } public static void setDuration(long duration) { condition_duration = duration; } public static void setFileMaxSize(long fileMaxSize) { condition_file_max_size = fileMaxSize * 1024 * 1024; } public static void setClearFile(int clearfile) { clear_file = clearfile == 1; } LogcatReceiver receiver; private void registerLogcatReceiver() { receiver = new LogcatReceiver(); IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(LOGCAT_START_ACTION); filter.addAction(LOGCAT_STOP_ACTION); registerReceiver(receiver, filter); } Thread thread = null; private void creatLogThread() { if (thread == null) { thread = new Thread(LogcatRunnale); } } private void startLogThread() { if (thread == null) { creatLogThread(); shouldGetLog = true; thread.start(); } else { //已经有线程正在运行了 } } private void stopLogThread() { if (thread != null) { shouldGetLog = false; thread = null; //清除adb 缓存 try { Runtime.getRuntime().exec(clearLogcat); } catch (IOException e) { e.printStackTrace(); } } uploadFile(); } private Process exec; private LogThread logThread; //第一个是Logcat ,也就是我们想要获取的log日志 //第二个是 -s 也就是表示过滤的意思 //第三个就是 我们要过滤的类型 W表示warm ,我们也可以换成 D :debug, I:info,E:error等等 // String[] running = new String[]{"logcat", "-s", "adb logcat *: W"}; String[] running = new String[]{"logcat"}; String clearLogcat = "logcat -c"; String logFilePath; //= getExternalCacheDir() + File.separator + "LOG" + File.separator; String logFileName; String tempFilePath; class LogThread extends Thread { InputStream is; LogThread(InputStream inputStream) { super(); this.is = inputStream; } @Override public void run() { FileOutputStream os = null; try { //新建一个路径信息 File file = new File(logFilePath + logFileName); Log.e(TAG, "run: " + logFilePath); if (!file.exists()) { file.getParentFile().mkdirs(); file.createNewFile(); } os = new FileOutputStream(logFilePath); int len = 0; byte[] buf = new byte[1024]; while (-1 != (len = is.read(buf))) { os.write(buf, 0, len); os.flush(); } } catch (Exception e) { Log.e("writelog", "read logcat process failed. message: " + e.getMessage()); } finally { if (null != os) { try { os.close(); os = null; } catch (IOException e) { // Do nothing } } } } } private Runnable LogcatRunnale = this::getLog; public static boolean shouldGetLog = true; private void getLog() { Process process = null; try { process = Runtime.getRuntime().exec(running); } catch (IOException e) { e.printStackTrace(); } InputStreamReader inputStreamReader; BufferedReader bufferedReader; FileOutputStream fileOutputStream; File file = new File(logFilePath); Log.e(TAG, "getLog: " + logFilePath); if (!file.exists()) { file.mkdirs(); } if (clear_file) { logFileName = Utils.getSerial(this) + ".log"; } else { logFileName = Utils.getSerial(this) + "-" + getTime() + ".log"; } try { inputStreamReader = new InputStreamReader(process.getInputStream()); bufferedReader = new BufferedReader(inputStreamReader); tempFilePath = logFilePath + logFileName; fileOutputStream = new FileOutputStream(tempFilePath); Log.e(TAG, "getLog: " + tempFilePath); long fileSize = file.length(); String logEntry; while (shouldGetLog) { logEntry = bufferedReader.readLine() + "\n"; fileOutputStream.write(logEntry.getBytes()); fileOutputStream.flush(); fileSize += logEntry.length(); // Log.e(TAG, "getLog: " + fileSize); if (fileSize >= condition_file_max_size || (start_Time + condition_duration) * 1000 < System.currentTimeMillis()) { shouldGetLog = false; stopLogThread(); } } inputStreamReader.close(); bufferedReader.close(); fileOutputStream.close(); Log.e(TAG, "getLog: " + "closed"); } catch (IOException e) { e.printStackTrace(); } catch (NullPointerException e) { e.printStackTrace(); } } private void uploadFile() { File file = new File(tempFilePath); if (!file.exists() || file.isDirectory()) { Log.e("uploadFile", "File does not exists"); return; } Map params = new HashMap<>(); params.put("sn", Utils.getSerial(this)); MediaType mediaType = MediaType.Companion.parse("text/html"); RequestBody fileBody = RequestBody.Companion.create(file, mediaType); //设置一个file文件 MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), fileBody); NetInterfaceManager.getInstance().getUploadLogApi() .UploadLog(params, body) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { Log.e("uploadFile", "onSubscribe: "); } @Override public void onNext(BaseResponse snRunLogBaseResponse) { Log.e("uploadFile", "onNext: " + snRunLogBaseResponse); } @Override public void onError(Throwable e) { Log.e("uploadFile", "onError: " + e.getMessage()); } @Override public void onComplete() { Log.e("uploadFile", "onComplete: "); if (clear_file) { file.delete(); } } }); } class LogcatReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.e(TAG, "onReceive: " + action); if (TextUtils.isEmpty(action)) { return; } switch (action) { case LOGCAT_START_ACTION: Log.e(TAG, "onReceive: "+"开始录制log"); startLogThread(); break; case LOGCAT_STOP_ACTION: Log.e(TAG, "onReceive: "+"停止录制log"); stopLogThread(); break; default: break; } } } public static String getTime() { long time = System.currentTimeMillis();//long now = android.os.SystemClock.uptimeMillis(); SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); Date d1 = new Date(time); String t1 = format.format(d1); return t1; } @Override public void onDestroy() { super.onDestroy(); if (receiver != null) { unregisterReceiver(receiver); } } }