Skip to content

Commit

Permalink
Merge pull request #9 from jpage4500/feature/08-01
Browse files Browse the repository at this point in the history
- get app working on Linux/Ubuntu
  • Loading branch information
jpage4500 authored Aug 1, 2024
2 parents e31014e + 4309d63 commit 313b57f
Show file tree
Hide file tree
Showing 16 changed files with 171 additions and 100 deletions.
19 changes: 19 additions & 0 deletions BUILD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Build Android Device Manager

## Prerequisites
- Java SDK
- min version 17; I'm using openjdk 22.0.1 2024-04-16
- MacOSX -> Homebrew -> `brew install openjdk`
- Linux - [link](https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-on-ubuntu-22-04)
- Maven
- MacOSX -> Homebrew -> `brew install maven`
- Linux - [link](https://www.digitalocean.com/community/tutorials/install-maven-linux-ubuntu)

## Build
- sync this repo
- `git clone https://github.com/jpage4500/AndroidDeviceManager.git`
- build
- `mvn compile`
- run:
- `mvn exec:java`

28 changes: 10 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,18 @@ Java desktop app to manage multiple Android devices via adb

## Requirements

- A recent Java Runtime Environment (**JRE**) (17+)
- NOTE: make sure java is in your system PATH
- to verify, open a terminal or command window and type `java --version`
- Java SDK
- min version 17; I'm using openjdk 22.0.1 2024-04-16
- MacOSX -> Homebrew -> `brew install openjdk`
- Linux - [link](https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-on-ubuntu-22-04)
- **adb**
- MacOSX -> homebrew -> `brew cask install android-platform-tools`
- Linux -> `sudo apt install adb fastboot`
- standalone adb tools can be found [here](https://developer.android.com/tools/releases/platform-tools)
- Mac OSX can install using brew:
- `brew cask install android-platform-tools`
- **scrcpy** - mirror a connected Android device ([https://github.com/Genymobile/scrcpy](https://github.com/Genymobile/scrcpy))
- Mac OSX can install using brew:
- `brew install scrcpy`
- MacOSX -> homebrew -> `brew install scrcpy`
- Linux -> see [link](https://github.com/Genymobile/scrcpy/blob/master/doc/linux.md#latest-version)
- make sure both `adb` and `scrcpy` are in the current PATH

## Run

Expand All @@ -56,17 +58,7 @@ Java desktop app to manage multiple Android devices via adb

## Build

NOTE: requires Maven installed and `mvn` available in PATH
- MacOSX can use brew to install:
- `brew install maven`


- sync this repo
- `git clone https://github.com/jpage4500/AndroidDeviceManager.git`
- build:
- `mvn install`
- run:
- `mvn exec:java`
[Build Instructions](BUILD.md)

## Use Cases ##

Expand Down
24 changes: 16 additions & 8 deletions scripts/clear-preferences.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
#!/bin/bash

PREFS=com.apple.java.util.prefs.plist
PREFS_FULL=~/Library/Preferences/$PREFS

# clear out all Preferences (NOTE: only tested on a Mac)
if [[ "$OSTYPE" == "darwin"* ]]; then
# Mac OSX
PREFS_FILE=~/Library/Preferences/com.apple.java.util.prefs.plist
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
# Linux
PREFS_FILE=~/.java/.userPrefs/prefs.xml
else
echo "unknown OS: $OSTYPE"
exit 1
fi

if [ -f $PREFS_FULL ]; then
echo "removing $PREFS_FULL.."
rm $PREFS_FULL
# clear out all Java Preferences
if [ -f $PREFS_FILE ]; then
echo "removing $PREFS_FILE.."
rm $PREFS_FILE

USER=$(id -un)
echo "clearing cache for $USER.."
killall -u $USER cfprefsd
else
echo "Preferences not found: $PREFS_FULL"
fi
echo "Preferences not found: $PREFS_FILE"
fi
5 changes: 5 additions & 0 deletions scripts/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

cd ..

mvn compile exec:java
34 changes: 21 additions & 13 deletions src/main/java/com/jpage4500/devicemanager/MainApplication.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package com.jpage4500.devicemanager;

import com.formdev.flatlaf.FlatLightLaf;
import com.jpage4500.devicemanager.logging.AppLogger;
import com.jpage4500.devicemanager.logging.AppLoggerFactory;
import com.jpage4500.devicemanager.logging.Log;
import com.jpage4500.devicemanager.ui.DeviceScreen;
import com.jpage4500.devicemanager.utils.PreferenceUtils;
import com.jpage4500.devicemanager.utils.UiUtils;
import com.jpage4500.devicemanager.utils.Utils;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Properties;

Expand Down Expand Up @@ -50,30 +54,34 @@ public static void main(String[] args) {
* - call soon after Application:onCreate(); can be called again if debug mode changes
*/
private void setupLogging() {
AppLoggerFactory logger = (AppLoggerFactory) LoggerFactory.getILoggerFactory();
// tag prefix allows for easy filtering: ie: 'adb logcat | grep PM_'
//logger.setTagPrefix("DM");
// set log level that application should log at (and higher)
logger.setDebugLevel(Log.VERBOSE);
logger.setLogToFile(true);
ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory();
if (iLoggerFactory instanceof AppLoggerFactory logger) {
// tag prefix allows for easy filtering: ie: 'adb logcat | grep PM_'
//logger.setTagPrefix("DM");
// set log level that application should log at (and higher)
logger.setDebugLevel(Log.VERBOSE);
logger.setLogToFile(true);

boolean isDebugMode = PreferenceUtils.getPreference(PreferenceUtils.PrefBoolean.PREF_DEBUG_MODE, false);
logger.setFileLogLevel(isDebugMode ? Log.DEBUG : Log.INFO);
boolean isDebugMode = PreferenceUtils.getPreference(PreferenceUtils.PrefBoolean.PREF_DEBUG_MODE, false);
logger.setFileLogLevel(isDebugMode ? Log.DEBUG : Log.INFO);
} else {
System.out.println("ERROR: no logger found: " + iLoggerFactory.getClass().getSimpleName());
}
}

private void initializeUI() {
FlatLightLaf.setup();
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
defaults.put("defaultFont", new Font("Arial", Font.PLAIN, 16));
defaults.put("Button.defaultButtonFollowsFocus", Boolean.TRUE);

// set docker app icon (mac)
if (Utils.isMac()) {
final Taskbar taskbar = Taskbar.getTaskbar();
if (Taskbar.isTaskbarSupported()) {
try {
Image image = ImageIO.read(getClass().getResource("/images/logo.png"));
Taskbar taskbar = Taskbar.getTaskbar();
BufferedImage image = UiUtils.getImage("logo.png", 256);
taskbar.setIconImage(image);
} catch (final Exception e) {
log.error("Exception: {}", e.getMessage());
log.error("initializeUI: Taskbar Exception: {}", e.getMessage());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public Device getDeviceAtRow(int row) {
* return one of the predefined columns or NULL if this is an app version column
*/
public Columns getColumnType(int colIndex) {
if (colIndex < visibleColumns.length) {
if (colIndex >= 0 && colIndex < visibleColumns.length) {
return visibleColumns[colIndex];
}
return null;
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/jpage4500/devicemanager/ui/BaseScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import com.jpage4500.devicemanager.utils.GsonHelper;
import com.jpage4500.devicemanager.utils.PreferenceUtils;
import com.jpage4500.devicemanager.utils.UiUtils;
import com.jpage4500.devicemanager.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.prefs.Preferences;

/**
Expand Down Expand Up @@ -64,6 +66,13 @@ public void windowClosed(WindowEvent e) {

// NOTE: this breaks dragging the scrollbar on Mac
// getRootPane().putClientProperty("apple.awt.draggableWindowBackground", true);

// TODO: not sure if this is used.. I don't see it on Mac or Linux
//if (!Utils.isMac()) {
// BufferedImage image = UiUtils.getImage("system_tray.png", 100, 100);
// setIconImage(image);
//}

}

public enum WindowState {
Expand Down
37 changes: 26 additions & 11 deletions src/main/java/com/jpage4500/devicemanager/ui/DeviceScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public class DeviceScreen extends BaseScreen implements DeviceManager.DeviceList
private static final Logger log = LoggerFactory.getLogger(DeviceScreen.class);

private static final String HINT_FILTER_DEVICES = "Filter devices...";
public static final String SHOW_DEVICE_LIST = "Show Device List";
public static final String SHOW_BROWSE = "Show File Browser";
public static final String SHOW_LOG_VIEWER = "Show Device Logs";

public CustomTable table;
public DeviceTableModel model;
Expand All @@ -59,7 +62,7 @@ public class DeviceScreen extends BaseScreen implements DeviceManager.DeviceList

public DeviceScreen() {
super("main", 900, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
initalizeUi();

connectAdbServer();
Expand Down Expand Up @@ -141,21 +144,34 @@ protected void initalizeUi() {
setupMenuBar();
setupSystemTray();
setContentPane(panel);

setVisible(true);

table.requestFocus();

if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
desktop.setQuitHandler((quitEvent, quitResponse) -> {
handleAppExit();
quitResponse.performQuit();
});
if (desktop.isSupported(Desktop.Action.APP_QUIT_HANDLER)) {
desktop.setQuitHandler((quitEvent, quitResponse) -> {
handleAppExit();
quitResponse.performQuit();
});
} else {
Runtime.getRuntime().addShutdownHook(new Thread(this::handleAppExit));
}
} else {
Runtime.getRuntime().addShutdownHook(new Thread(this::handleAppExit));
}
}

@Override
protected void onWindowStateChanged(WindowState state) {
super.onWindowStateChanged(state);
if (state == WindowState.CLOSING) {
exitApp();
}
}

private void exitApp() {
handleAppExit();
setVisible(false);
Expand Down Expand Up @@ -184,10 +200,10 @@ private void setupMenuBar() {
});

// [CMD + 2] = show explorer
createCmdAction(windowMenu, "Browse Files", KeyEvent.VK_2, e -> handleBrowseCommand());
createCmdAction(windowMenu, SHOW_BROWSE, KeyEvent.VK_2, e -> handleBrowseCommand());

// [CMD + 3] = show logs
createCmdAction(windowMenu, "View Logs", KeyEvent.VK_3, e -> handleLogsCommand());
createCmdAction(windowMenu, SHOW_LOG_VIEWER, KeyEvent.VK_3, e -> handleLogsCommand());

// [CMD + ,] = settings
createCmdAction(windowMenu, "Settings", KeyEvent.VK_COMMA, e -> handleSettingsClicked());
Expand Down Expand Up @@ -252,12 +268,11 @@ private void setupTable() {
table.setPreferredColWidth(DeviceTableModel.Columns.IMEI.name(), 147);
table.setPreferredColWidth(DeviceTableModel.Columns.BATTERY.name(), 31);
table.setPreferredColWidth(DeviceTableModel.Columns.FREE.name(), 66);
// set max sizes
table.setMaxColWidth(DeviceTableModel.Columns.BATTERY.name(), 31);
table.setMaxColWidth(DeviceTableModel.Columns.FREE.name(), 80);
}

// set max sizes
table.setMaxColWidth(DeviceTableModel.Columns.BATTERY.name(), 31);
table.setMaxColWidth(DeviceTableModel.Columns.FREE.name(), 80);

sorter = new DeviceRowSorter(model);
table.setRowSorter(sorter);

Expand Down
15 changes: 4 additions & 11 deletions src/main/java/com/jpage4500/devicemanager/ui/ExploreScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,6 @@ protected void initalizeUi() {
setupMenuBar();
setupPopupMenu();

addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
closeWindow();
}
});

table.requestFocus();
}

Expand All @@ -122,8 +115,7 @@ private void setupStatusBar() {
protected void onWindowStateChanged(WindowState state) {
super.onWindowStateChanged(state);
if (state == WindowState.CLOSED) {
saveFrameSize();
table.saveTable();
closeWindow();
}
}

Expand All @@ -134,10 +126,10 @@ private void setupMenuBar() {
createCmdAction(windowMenu, "Close Window", KeyEvent.VK_W, e -> closeWindow());

// [CMD + 1] = show devices
createCmdAction(windowMenu, "Show Devices", KeyEvent.VK_1, e -> deviceScreen.toFront());
createCmdAction(windowMenu, DeviceScreen.SHOW_DEVICE_LIST, KeyEvent.VK_1, e -> deviceScreen.toFront());

// [CMD + 3] = show logs
createCmdAction(windowMenu, "View Logs", KeyEvent.VK_3, e -> deviceScreen.handleLogsCommand());
createCmdAction(windowMenu, DeviceScreen.SHOW_LOG_VIEWER, KeyEvent.VK_3, e -> deviceScreen.handleLogsCommand());

// [CMD + T] = hide toolbar
createCmdAction(windowMenu, "Hide Toolbar", KeyEvent.VK_T, e -> hideToolbar());
Expand All @@ -158,6 +150,7 @@ private void setupMenuBar() {

private void closeWindow() {
log.trace("closeWindow: {}", device.getDisplayName());
saveFrameSize();
table.saveTable();
deviceScreen.handleBrowseClosed(device.serial);
dispose();
Expand Down
16 changes: 9 additions & 7 deletions src/main/java/com/jpage4500/devicemanager/ui/InputScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,6 @@ private void initalizeUi() {
JPanel panel = new JPanel(new BorderLayout());
panel.setLayout(new MigLayout("fillx", "[][]"));

addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
closeWindow();
}
});

setupMenuBar();

panel.add(new JLabel("Recent Text"), "growx, span 2, wrap");
Expand Down Expand Up @@ -132,8 +125,17 @@ private void setupMenuBar() {
setJMenuBar(menubar);
}

@Override
protected void onWindowStateChanged(WindowState state) {
super.onWindowStateChanged(state);
if (state == WindowState.CLOSED) {
closeWindow();
}
}

private void closeWindow() {
log.trace("closeWindow: {}", device.getDisplayName());
saveFrameSize();
deviceScreen.handleInputClosed(device.serial);
dispose();
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/jpage4500/devicemanager/ui/LogsScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,10 @@ private void setupMenuBar() {
createCmdAction(windowMenu, "Close Window", KeyEvent.VK_W, e -> closeWindow());

// [CMD + 1] = show devices
createCmdAction(windowMenu, "Show Devices", KeyEvent.VK_1, e -> deviceScreen.toFront());
createCmdAction(windowMenu, DeviceScreen.SHOW_DEVICE_LIST, KeyEvent.VK_1, e -> deviceScreen.toFront());

// [CMD + 2] = show explorer
createCmdAction(windowMenu, "Browse Files", KeyEvent.VK_2, e -> deviceScreen.handleBrowseCommand());
createCmdAction(windowMenu, DeviceScreen.SHOW_BROWSE, KeyEvent.VK_2, e -> deviceScreen.handleBrowseCommand());

// [CMD + T] = hide toolbar
createCmdAction(windowMenu, "Hide Toolbar", KeyEvent.VK_T, e -> hideToolbar());
Expand Down
Loading

0 comments on commit 313b57f

Please sign in to comment.