package com.josesamuel.logviewer.log.device; import com.android.ddmlib.Client; import com.android.ddmlib.IDevice; import com.android.ddmlib.logcat.LogCatHeader; import com.android.ddmlib.logcat.LogCatMessage; import com.android.tools.idea.logcat.AndroidLogcatService; import com.google.common.collect.Lists; import com.josesamuel.logviewer.util.UIUtil; import com.josesamuel.logviewer.log.LogDataListener; import com.josesamuel.logviewer.log.LogDataProvider; import com.josesamuel.logviewer.log.LogProcess; import com.josesamuel.logviewer.view.AndroidLogcatFormatter; import com.josesamuel.logviewer.view.ClientCellRenderer; import org.jetbrains.annotations.NotNull; import java.util.HashSet; import java.util.List; import java.util.Set; /** * {@link LogDataProvider} for actual device */ public class DeviceLogDataProvider implements LogDataProvider, AndroidLogcatService.LogcatListener { private LogCatHeader myActiveHeader; private LogDataListener logListener; private IDevice device; /** * Initialize this with the given device */ DeviceLogDataProvider(IDevice device) { this.device = device; } @Override public void registerLogListener(LogDataListener logListener) { this.logListener = logListener; AndroidLogcatService.getInstance().addListener(device, this, true); updateProcessList(); } @Override public void unRegisterLogListener(LogDataListener logListener) { this.logListener = null; AndroidLogcatService.getInstance().removeListener(device, this); } @Override public void onLogLineReceived(@NotNull LogCatMessage line) { try { LogProcess logProcess = new LogProcess(); logProcess.setProcessID(line.getPid()); String appName = line.getAppName(); if (appName == null || appName.isEmpty() || appName.equals("?")) { appName = line.getTag(); if (appName == null || appName.isEmpty() || appName.equals("?")) { appName = "TAG"; } } logProcess.setProcessName(appName); String message = null; if (!line.getHeader().equals(myActiveHeader)) { myActiveHeader = line.getHeader(); message = AndroidLogcatFormatter.formatMessageFull(myActiveHeader, line.getMessage()); } else { message = AndroidLogcatFormatter.formatContinuation(line.getMessage()); } if (message != null) { notifyLog(message, logProcess); } } catch (Exception ex) { logListener.debug(ex.getMessage()); } } /** * Notify a new line is added */ private void notifyLog(String logLine, LogProcess process) { UIUtil.invokeLaterIfNeeded(() -> { try { if (logListener != null) { logListener.onLogLine(logLine, process); } } catch (Exception ignored) { } }); } @Override public void onCleared() { UIUtil.invokeLaterIfNeeded(() -> { if (logListener != null) { logListener.onCleared(); } }); } /** * Clean up */ public void dispose() { AndroidLogcatService.getInstance().removeListener(device, this); this.logListener = null; } /** * Updates the process list */ public void updateProcessList() { if (logListener != null) { UIUtil.invokeLaterIfNeeded(() -> { try { if (device != null && logListener != null) { List<Client> clients = Lists.newArrayList(device.getClients()); clients.sort(new ClientCellRenderer.ClientComparator()); logListener.onProcessList(toLogProcess(clients)); } } catch (Exception ignored) { } }); } } /** * Convert list of {@link Client} to list of {@link LogProcess} */ private Set<LogProcess> toLogProcess(List<Client> clientList) { Set<LogProcess> logProcesses = new HashSet<>(); for (Client client : clientList) { if (client != null) { logProcesses.add(new LogProcess(client)); } } return logProcesses; } }