diff --git a/.travis.yml b/.travis.yml
index e040132..1e6f6ed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,5 @@
language: java
-branches:
- only:
- - master
before_install:
- chmod +x mvnw
jdk:
diff --git a/README.md b/README.md
index 94655bc..550960a 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,11 @@
AndroidScreencast
=================
-[![Build Status Travis-CI][travis_badge]][travis] [![Dependency Status][versioneye_badge]][versioneye] [![Codacy Badge][codacy_badge]][codacy] [![Join the chat at https://gitter.im/AndroidScreencast/Lobby][gitter_badge]][gitter]
-
-[travis_badge]: https://travis-ci.org/xSAVIKx/AndroidScreencast.svg?branch=master
-[travis]: https://travis-ci.org/xSAVIKx/AndroidScreencast
-
-[versioneye_badge]: https://www.versioneye.com/user/projects/588988221618a700318eafb5/badge.svg
-[versioneye]: https://www.versioneye.com/user/projects/588988221618a700318eafb5
-
-[codacy_badge]: https://api.codacy.com/project/badge/Grade/064bbd2582b544bb9659a01a2872317c
-[codacy]: https://www.codacy.com/app/xSAVIKx/AndroidScreencast?utm_source=github.com&utm_medium=referral&utm_content=xSAVIKx/AndroidScreencast&utm_campaign=badger
-
-
-
-[gitter_badge]: https://badges.gitter.im/AndroidScreencast/Lobby.svg
-[gitter]: https://gitter.im/AndroidScreencast/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
+[![Build Status Travis-CI][travis_badge]][travis]
+[![Dependency Status][versioneye_badge]][versioneye]
+[![Codacy Badge][codacy_badge]][codacy]
+[![Join the chat at https://gitter.im/AndroidScreencast/Lobby][gitter_badge]][gitter]
+[![Apache License][license_badge]][license]
# Description
@@ -62,7 +52,7 @@ The resulting artifacts will be created in the `target` subdirectory.
You can run the executable jar via `java -jar target/androidscreencast-VERSION-executable.jar`, replacing VERSION with
the current version.
-For example, `java -jar target/androidscreencast-0.0.9s-executable.jar`.
+For example, `java -jar target/androidscreencast-0.0.10s-executable.jar`.
Additionally OS-packages would be created with ADB executables bundled:
* `androidscreencast-VERSION-windows.zip`
@@ -82,4 +72,27 @@ So, right now AndroidScreencast support all Android versions equal or greater th
Also, to run AndroidScreencast you will need *adb* installed (or you can use bundled in OS bundles adb).
+# Similar Projects
+
+* [Seven Square][seven_square] - QT implementation of Android Screencast (actively developed)
+* [Droid@Screen][droid_at_screen] - implementation of Android Screencast in Java (fancy one, last release in 2013)
+* [Android Screen Monitor][android_screen_monitor] - implementation of Android Screencast in Java (latest release in 2013)
+
[Android_4_1_1_Input]: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/com/android/commands/input/Input.java#Input
+[seven_square]: https://github.com/yangh/sevensquare
+[droid_at_screen]: http://droid-at-screen.org/droid-at-screen/
+
+[travis_badge]: https://travis-ci.org/xSAVIKx/AndroidScreencast.svg?branch=master
+[travis]: https://travis-ci.org/xSAVIKx/AndroidScreencast
+
+[versioneye_badge]: https://www.versioneye.com/user/projects/58a746d8b4d2a20055fcb887/badge.svg?style=flat
+[versioneye]: https://www.versioneye.com/user/projects/58a746d8b4d2a20055fcb887
+
+[codacy_badge]: https://api.codacy.com/project/badge/Grade/064bbd2582b544bb9659a01a2872317c
+[codacy]: https://www.codacy.com/app/xSAVIKx/AndroidScreencast?utm_source=github.com&utm_medium=referral&utm_content=xSAVIKx/AndroidScreencast&utm_campaign=badger
+
+[license_badge]: https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat
+[license]: http://www.apache.org/licenses/LICENSE-2.0
+
+[gitter_badge]: https://badges.gitter.im/AndroidScreencast/Lobby.svg?style=flat
+[gitter]: https://gitter.im/AndroidScreencast/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
diff --git a/app.properties b/app.properties
index 2d7c1f7..1175efc 100644
--- a/app.properties
+++ b/app.properties
@@ -1,3 +1,3 @@
-adb.path=adb/windows/adb.exe
+adb.path=adb/windows/adb2.exe
default.window.width=1024
default.window.height=768
\ No newline at end of file
diff --git a/docs/jnlp/androidscreencast.jnlp b/docs/jnlp/androidscreencast.jnlp
index c3ac0d2..d3c68dd 100644
--- a/docs/jnlp/androidscreencast.jnlp
+++ b/docs/jnlp/androidscreencast.jnlp
@@ -1,7 +1,7 @@
+ version="0.0.10s">
Android Screencast
Iurii Sergiichuk
@@ -16,7 +16,7 @@
+ href="https://github.com/xSAVIKx/AndroidScreencast/releases/download/0.0.10s/androidscreencast-0.0.10s-executable.jar"/>
diff --git a/pom.xml b/pom.xml
index 1802285..a004b8e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,12 +3,14 @@
4.0.0
com.github.xsavikx
androidscreencast
- 0.0.9s
+ 0.0.10s
Android Screencast
+ jar
- 4.3.5.RELEASE
+ 2.9
25.2.0
- 1.2.17
+ 1.7.24
+ 1.2.1
21.0
com.github.xsavikx.androidscreencast.Main
1.8
@@ -25,24 +27,31 @@
${ddmlib.version}
- log4j
- log4j
- ${log4j.version}
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
- org.springframework
- spring-core
- ${spring.version}
+ ch.qos.logback
+ logback-classic
+ ${logback-classic.version}
- org.springframework
- spring-beans
- ${spring.version}
+ org.slf4j
+ jcl-over-slf4j
+ ${slf4j.version}
- org.springframework
- spring-context
- ${spring.version}
+ com.google.dagger
+ dagger
+ ${dagger2.version}
+
+
+ com.google.dagger
+ dagger-compiler
+ ${dagger2.version}
+ true
+ provided
com.google.guava
@@ -75,7 +84,7 @@
org.apache.maven.plugins
maven-shade-plugin
- 2.4.3
+ 3.0.0
package
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/Main.java b/src/main/java/com/github/xsavikx/androidscreencast/Main.java
index 32a10bb..cb5e810 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/Main.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/Main.java
@@ -1,24 +1,23 @@
package com.github.xsavikx.androidscreencast;
-import com.github.xsavikx.androidscreencast.app.AndroidScreencastApplication;
import com.github.xsavikx.androidscreencast.app.Application;
-import com.github.xsavikx.androidscreencast.spring.config.ApplicationContextProvider;
-import org.apache.log4j.Logger;
+import com.github.xsavikx.androidscreencast.dagger.MainComponentProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.Arrays;
public class Main {
- private static final Logger LOGGER = Logger.getLogger(Main.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
public static void main(String args[]) {
- LOGGER.debug("main(String[] args=" + Arrays.toString(args) + ") - start");
- Application application;
+ LOGGER.debug("main(String[] args={}) - start", Arrays.toString(args));
try {
- application = ApplicationContextProvider.getBean(AndroidScreencastApplication.class);
+ Application application = MainComponentProvider.mainComponent().application();
application.init();
application.start();
} finally {
- LOGGER.debug("main(String[] args=" + Arrays.toString(args) + ") - end");
+ LOGGER.debug("main(String[] args={}) - end", Arrays.toString(args));
}
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/AndroidDeviceImpl.java b/src/main/java/com/github/xsavikx/androidscreencast/api/AndroidDeviceImpl.java
index f19ac15..295d671 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/AndroidDeviceImpl.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/AndroidDeviceImpl.java
@@ -7,55 +7,56 @@
import com.github.xsavikx.androidscreencast.api.injector.OutputStreamShellOutputReceiver;
import com.github.xsavikx.androidscreencast.exception.AndroidScreenCastRuntimeException;
import com.github.xsavikx.androidscreencast.exception.ExecuteCommandException;
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
-@Component
+@Singleton
public class AndroidDeviceImpl implements AndroidDevice {
- private static final Logger logger = Logger.getLogger(AndroidDeviceImpl.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(AndroidDeviceImpl.class);
private final IDevice device;
- @Autowired
- public AndroidDeviceImpl(IDevice device) {
+ @Inject
+ public AndroidDeviceImpl(final IDevice device) {
this.device = device;
}
@Override
- public String executeCommand(String cmd) {
- if (logger.isDebugEnabled()) {
- logger.debug("executeCommand(String) - start");
+ public String executeCommand(final String cmd) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("executeCommand(String) - start");
}
- try (ByteArrayOutputStream bos = new ByteArrayOutputStream();) {
+ try (final ByteArrayOutputStream bos = new ByteArrayOutputStream();) {
device.executeShellCommand(cmd, new OutputStreamShellOutputReceiver(bos));
- String returnString = new String(bos.toByteArray(), "UTF-8");
- if (logger.isDebugEnabled()) {
- logger.debug("executeCommand(String) - end");
+ final String returnString = new String(bos.toByteArray(), "UTF-8");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("executeCommand(String) - end");
}
return returnString;
- } catch (Exception ex) {
- logger.error("executeCommand(String)", ex);
+ } catch (final Exception ex) {
+ LOGGER.error("executeCommand(String)", ex);
throw new ExecuteCommandException(cmd);
}
}
@Override
- public List list(String path) {
- if (logger.isDebugEnabled()) {
- logger.debug("list(String) - start");
+ public List list(final String path) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("list(String) - start");
}
try {
- String s = executeCommand("ls -l " + path);
- String[] entries = s.split("\r\n");
- List fileInfos = new ArrayList<>();
- for (String entry : entries) {
+ final String s = executeCommand("ls -l " + path);
+ final String[] entries = s.split("\r\n");
+ final List fileInfos = new ArrayList<>();
+ for (final String entry : entries) {
String[] data = entry.split(" ");
if (data.length < 4)
continue;
@@ -63,7 +64,7 @@ public List list(String path) {
boolean directory = attributes.charAt(0) == 'd';
String name = data[data.length - 1];
- FileInfo fi = new FileInfo();
+ final FileInfo fi = new FileInfo();
fi.attribs = attributes;
fi.directory = directory;
fi.name = name;
@@ -73,59 +74,59 @@ public List list(String path) {
fileInfos.add(fi);
}
- if (logger.isDebugEnabled()) {
- logger.debug("list(String) - end");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("list(String) - end");
}
return fileInfos;
- } catch (Exception ex) {
- logger.error("list(String)", ex);
+ } catch (final Exception ex) {
+ LOGGER.error("list(String)", ex);
throw new AndroidScreenCastRuntimeException(ex);
}
}
@Override
- public void openUrl(String url) {
- if (logger.isDebugEnabled()) {
- logger.debug("openUrl(String) - start");
+ public void openUrl(final String url) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("openUrl(String) - start");
}
executeCommand("am start " + url);
- if (logger.isDebugEnabled()) {
- logger.debug("openUrl(String) - end");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("openUrl(String) - end");
}
}
@Override
- public void pullFile(String removeFrom, File localTo) {
- if (logger.isDebugEnabled()) {
- logger.debug("pullFile(String, File) - start");
+ public void pullFile(final String removeFrom, final File localTo) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("pullFile(String, File) - start");
}
// ugly hack to call the method without FileEntry
try {
if (device.getSyncService() == null)
- throw new RuntimeException("SyncService is null, ADB crashed ?");
- Method m = device.getSyncService().getClass().getDeclaredMethod("doPullFile", String.class, String.class,
+ throw new AndroidScreenCastRuntimeException("SyncService is null, ADB crashed ?");
+ final Method m = device.getSyncService().getClass().getDeclaredMethod("doPullFile", String.class, String.class,
ISyncProgressMonitor.class);
m.setAccessible(true);
device.getSyncService();
m.invoke(device.getSyncService(), removeFrom, localTo.getAbsolutePath(), SyncService.getNullProgressMonitor());
- } catch (Exception ex) {
- logger.error("pullFile(String, File)", ex);
+ } catch (final Exception ex) {
+ LOGGER.error("pullFile(String, File)", ex);
throw new AndroidScreenCastRuntimeException(ex);
}
- if (logger.isDebugEnabled()) {
- logger.debug("pullFile(String, File) - end");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("pullFile(String, File) - end");
}
}
@Override
- public void pushFile(File localFrom, String remoteTo) {
- if (logger.isDebugEnabled()) {
- logger.debug("pushFile(File, String) - start");
+ public void pushFile(final File localFrom, final String remoteTo) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("pushFile(File, String) - start");
}
try {
@@ -134,14 +135,14 @@ public void pushFile(File localFrom, String remoteTo) {
device.getSyncService().pushFile(localFrom.getAbsolutePath(), remoteTo, SyncService.getNullProgressMonitor());
- } catch (Exception ex) {
- logger.error("pushFile(File, String)", ex);
+ } catch (final Exception ex) {
+ LOGGER.error("pushFile(File, String)", ex);
throw new AndroidScreenCastRuntimeException(ex);
}
- if (logger.isDebugEnabled()) {
- logger.debug("pushFile(File, String) - end");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("pushFile(File, String) - end");
}
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/adb/AndroidDebugBridgeWrapper.java b/src/main/java/com/github/xsavikx/androidscreencast/api/adb/AndroidDebugBridgeWrapper.java
new file mode 100644
index 0000000..d9e9a90
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/adb/AndroidDebugBridgeWrapper.java
@@ -0,0 +1,71 @@
+package com.github.xsavikx.androidscreencast.api.adb;
+
+import com.android.ddmlib.AndroidDebugBridge;
+import com.android.ddmlib.IDevice;
+import com.github.xsavikx.androidscreencast.exception.IllegalAdbConfigurationException;
+import com.github.xsavikx.androidscreencast.util.StringUtils;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import java.io.IOException;
+
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.ADB_PATH_KEY;
+
+@Singleton
+public class AndroidDebugBridgeWrapper {
+ private final String adbPath;
+ private AndroidDebugBridge adb;
+
+ @Inject
+ public AndroidDebugBridgeWrapper(@Named(ADB_PATH_KEY) String adbPath) {
+ this.adbPath = adbPath;
+ }
+
+ public IDevice[] getDevices() {
+ return getAdb().getDevices();
+ }
+
+ public boolean hasInitialDeviceList() {
+ return getAdb().hasInitialDeviceList();
+ }
+
+ public void stop() {
+ AndroidDebugBridge.disconnectBridge();
+ AndroidDebugBridge.terminate();
+ }
+
+ private AndroidDebugBridge getAdb() {
+ if (adb == null) {
+ init();
+ }
+ return adb;
+ }
+
+ private void init() {
+ if (adb != null) {
+ return;
+ }
+ try {
+ AndroidDebugBridge.initIfNeeded(false);
+ if (StringUtils.isNotEmpty(adbPath)) {
+ adb = AndroidDebugBridge.createBridge(adbPath, false);
+ } else {
+ adb = AndroidDebugBridge.createBridge();
+ }
+ } catch (IllegalArgumentException e) {
+ if (hasAdbProcFailed(e)) {
+ throw new IllegalAdbConfigurationException(adbPath);
+ }
+ throw e;
+ }
+ }
+
+ private boolean hasAdbProcFailed(IllegalArgumentException e) {
+ return e.getCause() != null
+ && e.getCause() instanceof IOException
+ && e.getCause().getMessage().contains("Cannot run program")
+ && e.getCause().getMessage().contains("adb");
+
+ }
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/command/executor/ShellCommandExecutor.java b/src/main/java/com/github/xsavikx/androidscreencast/api/command/executor/ShellCommandExecutor.java
index 1327533..41a3830 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/command/executor/ShellCommandExecutor.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/command/executor/ShellCommandExecutor.java
@@ -7,41 +7,46 @@
import com.github.xsavikx.androidscreencast.api.command.Command;
import com.github.xsavikx.androidscreencast.api.command.exception.AdbShellCommandExecutionException;
import com.github.xsavikx.androidscreencast.api.injector.MultiLineReceiverPrinter;
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
-@Service
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.ADB_COMMAND_TIMEOUT_KEY;
+
+@Singleton
public class ShellCommandExecutor implements CommandExecutor {
- private static final Logger LOGGER = Logger.getLogger(ShellCommandExecutor.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ShellCommandExecutor.class);
private final IDevice device;
private final MultiLineReceiverPrinter multiLineReceiverPrinter;
- @Value("${adb.command.timeout:5}")
- private long adbCommandTimeout;
+ private final long adbCommandTimeout;
- @Autowired
- public ShellCommandExecutor(IDevice device, MultiLineReceiverPrinter multiLineReceiverPrinter) {
+ @Inject
+ public ShellCommandExecutor(final IDevice device,
+ final MultiLineReceiverPrinter multiLineReceiverPrinter,
+ @Named(ADB_COMMAND_TIMEOUT_KEY) long adbCommandTimeout) {
this.device = device;
this.multiLineReceiverPrinter = multiLineReceiverPrinter;
+ this.adbCommandTimeout = adbCommandTimeout;
}
@Override
public void execute(Command command) {
- LOGGER.debug("execute(Command command=" + command + ") - start");
+ LOGGER.debug("execute(Command command={}) - start", command);
try {
device.executeShellCommand(command.getFormattedCommand(), multiLineReceiverPrinter,
adbCommandTimeout, TimeUnit.SECONDS);
} catch (TimeoutException | AdbCommandRejectedException | ShellCommandUnresponsiveException | IOException e) {
- LOGGER.error("execute(Command)", e);
+ LOGGER.error("execute(Command command={})", command, e);
throw new AdbShellCommandExecutionException(command, e);
}
- LOGGER.debug("execute(Command command=" + command + ") - end");
+ LOGGER.debug("execute(Command command={}) - end", command);
}
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/command/factory/AdbInputCommandFactory.java b/src/main/java/com/github/xsavikx/androidscreencast/api/command/factory/AdbInputCommandFactory.java
index 6682e3c..0fe03aa 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/command/factory/AdbInputCommandFactory.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/command/factory/AdbInputCommandFactory.java
@@ -4,53 +4,47 @@
import com.github.xsavikx.androidscreencast.api.command.SwipeCommand;
import com.github.xsavikx.androidscreencast.api.command.TapCommand;
import com.github.xsavikx.androidscreencast.api.injector.InputKeyEvent;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-@Service
-public final class AdbInputCommandFactory {
- private static final Logger LOGGER = Logger.getLogger(AdbInputCommandFactory.class);
+import javax.inject.Inject;
+import javax.inject.Singleton;
- public static KeyCommand getKeyCommand(int keyCode) {
- KeyCommand returnKeyCommand = new KeyCommand(keyCode);
- LOGGER.debug(returnKeyCommand);
- return returnKeyCommand;
- }
-
- public static KeyCommand getKeyCommand(InputKeyEvent inputKeyEvent) {
- KeyCommand returnKeyCommand = new KeyCommand(inputKeyEvent);
- LOGGER.debug(returnKeyCommand);
- return returnKeyCommand;
- }
+@Singleton
+public class AdbInputCommandFactory implements InputCommandFactory {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AdbInputCommandFactory.class);
+ @Inject
+ public AdbInputCommandFactory() {
- public static KeyCommand getKeyCommand(int keyCode, boolean longpress) {
- KeyCommand returnKeyCommand = new KeyCommand(keyCode, longpress);
- LOGGER.debug(returnKeyCommand);
- return returnKeyCommand;
}
- public static KeyCommand getKeyCommand(InputKeyEvent inputKeyEvent, boolean longpress) {
- KeyCommand returnKeyCommand = new KeyCommand(inputKeyEvent, longpress);
- LOGGER.debug(returnKeyCommand);
+ @Override
+ public KeyCommand getKeyCommand(final int keyCode) {
+ final KeyCommand returnKeyCommand = new KeyCommand(keyCode);
+ LOGGER.debug(String.valueOf(returnKeyCommand));
return returnKeyCommand;
}
- public static SwipeCommand getSwipeCommand(int x1, int y1, int x2, int y2, long duration) {
- SwipeCommand returnSwipeCommand = new SwipeCommand(x1, y1, x2, y2, duration);
- LOGGER.debug(returnSwipeCommand);
- return returnSwipeCommand;
+ @Override
+ public KeyCommand getKeyCommand(final InputKeyEvent inputKeyEvent, final boolean longpress) {
+ final KeyCommand returnKeyCommand = new KeyCommand(inputKeyEvent, longpress);
+ LOGGER.debug(String.valueOf(returnKeyCommand));
+ return returnKeyCommand;
}
- public static SwipeCommand getSwipeCommand(int x1, int y1, int x2, int y2) {
- SwipeCommand returnSwipeCommand = new SwipeCommand(x1, y1, x2, y2);
- LOGGER.debug(returnSwipeCommand);
+ @Override
+ public SwipeCommand getSwipeCommand(final int x1, final int y1, final int x2, final int y2, final long duration) {
+ final SwipeCommand returnSwipeCommand = new SwipeCommand(x1, y1, x2, y2, duration);
+ LOGGER.debug(String.valueOf(returnSwipeCommand));
return returnSwipeCommand;
}
- public static TapCommand getTapCommand(int x, int y) {
- TapCommand returnTapCommand = new TapCommand(x, y);
- LOGGER.debug(returnTapCommand);
+ @Override
+ public TapCommand getTapCommand(final int x, final int y) {
+ final TapCommand returnTapCommand = new TapCommand(x, y);
+ LOGGER.debug(String.valueOf(returnTapCommand));
return returnTapCommand;
}
+
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/command/factory/InputCommandFactory.java b/src/main/java/com/github/xsavikx/androidscreencast/api/command/factory/InputCommandFactory.java
new file mode 100644
index 0000000..a8953d1
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/command/factory/InputCommandFactory.java
@@ -0,0 +1,16 @@
+package com.github.xsavikx.androidscreencast.api.command.factory;
+
+import com.github.xsavikx.androidscreencast.api.command.KeyCommand;
+import com.github.xsavikx.androidscreencast.api.command.SwipeCommand;
+import com.github.xsavikx.androidscreencast.api.command.TapCommand;
+import com.github.xsavikx.androidscreencast.api.injector.InputKeyEvent;
+
+public interface InputCommandFactory {
+ KeyCommand getKeyCommand(int keyCode);
+
+ KeyCommand getKeyCommand(InputKeyEvent inputKeyEvent, boolean longpress);
+
+ SwipeCommand getSwipeCommand(int x1, int y1, int x2, int y2, long duration);
+
+ TapCommand getTapCommand(int x, int y);
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/file/FileInfo.java b/src/main/java/com/github/xsavikx/androidscreencast/api/file/FileInfo.java
index 007de7f..a49804c 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/file/FileInfo.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/file/FileInfo.java
@@ -2,12 +2,13 @@
import com.github.xsavikx.androidscreencast.api.AndroidDeviceImpl;
import com.github.xsavikx.androidscreencast.exception.IORuntimeException;
-import org.springframework.stereotype.Component;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
-@Component
+@Singleton
public class FileInfo {
public AndroidDeviceImpl device;
public String path;
@@ -15,6 +16,11 @@ public class FileInfo {
public boolean directory;
public String name;
+ @Inject
+ public FileInfo() {
+
+ }
+
public File downloadTemporary() {
try {
File tempFile = File.createTempFile("android", name);
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/Injector.java b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/Injector.java
index eed9306..13fde3b 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/Injector.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/Injector.java
@@ -1,19 +1,19 @@
package com.github.xsavikx.androidscreencast.api.injector;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
+import javax.inject.Inject;
+import javax.inject.Singleton;
import java.io.File;
-@Service
+@Singleton
public class Injector {
private final ScreenCaptureRunnable screenCaptureRunnable;
private final Thread screenCaptureThread;
- @Autowired
- public Injector(ScreenCaptureRunnable screenCaptureRunnable) {
+ @Inject
+ public Injector(final ScreenCaptureRunnable screenCaptureRunnable) {
this.screenCaptureRunnable = screenCaptureRunnable;
this.screenCaptureThread = new Thread(screenCaptureRunnable, "Screen Capturer");
+ this.screenCaptureThread.setDaemon(true);
}
public void stop() {
@@ -24,11 +24,11 @@ public void start() {
screenCaptureThread.start();
}
- public void setScreenCaptureListener(ScreenCaptureRunnable.ScreenCaptureListener listener) {
+ public void setScreenCaptureListener(final ScreenCaptureRunnable.ScreenCaptureListener listener) {
this.screenCaptureRunnable.setListener(listener);
}
- public void startRecording(File file) {
+ public void startRecording(final File file) {
screenCaptureRunnable.startRecording(file);
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/InputKeyEvent.java b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/InputKeyEvent.java
index ddaa0f6..ddf8ceb 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/InputKeyEvent.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/InputKeyEvent.java
@@ -1,12 +1,10 @@
//@formatter:off
package com.github.xsavikx.androidscreencast.api.injector;
-import javax.annotation.Resource;
import java.awt.event.KeyEvent;
import java.util.EnumSet;
import java.util.Set;
-@Resource
public enum InputKeyEvent {
KEYCODE_UNKNOWN(0, "Key code constant: Unknown key code."),
KEYCODE_SOFT_LEFT(1, "Key code constant: Soft Left key. Usually situated below the display on phones and used as a multi-function feature key for selecting a software defined function shown on the bottom left of the display."),
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/KeyCodeConverter.java b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/KeyCodeConverter.java
index b9d8bd6..153b537 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/KeyCodeConverter.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/KeyCodeConverter.java
@@ -1,14 +1,15 @@
package com.github.xsavikx.androidscreencast.api.injector;
-import org.apache.log4j.Logger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.awt.event.KeyEvent;
public class KeyCodeConverter {
- private static final Logger LOGGER = Logger.getLogger(KeyCodeConverter.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(KeyCodeConverter.class);
public static int getKeyCode(KeyEvent e) {
- LOGGER.debug("getKeyCode(KeyEvent e=" + e + ") - start");
+ LOGGER.debug("getKeyCode(KeyEvent e={}) - start", e);
int code = InputKeyEvent.KEYCODE_UNKNOWN.getCode();
char c = e.getKeyChar();
int keyCode = e.getKeyCode();
@@ -16,7 +17,7 @@ public static int getKeyCode(KeyEvent e) {
if (inputKeyEvent != null) {
code = inputKeyEvent.getCode();
}
- LOGGER.debug(String.format("Received KeyEvent=%s. Produced KeyCode=%d", String.valueOf(e), code));
+ LOGGER.debug("Received KeyEvent={}. Produced KeyCode={}", String.valueOf(e), code);
return code;
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/MultiLineReceiverPrinter.java b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/MultiLineReceiverPrinter.java
index d33a9ce..0233842 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/MultiLineReceiverPrinter.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/MultiLineReceiverPrinter.java
@@ -1,10 +1,16 @@
package com.github.xsavikx.androidscreencast.api.injector;
import com.android.ddmlib.MultiLineReceiver;
-import org.springframework.stereotype.Component;
-@Component
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
public class MultiLineReceiverPrinter extends MultiLineReceiver {
+ @Inject
+ public MultiLineReceiverPrinter() {
+
+ }
@Override
public boolean isCancelled() {
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/ScreenCaptureRunnable.java b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/ScreenCaptureRunnable.java
index 7d2a16f..2fa4169 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/injector/ScreenCaptureRunnable.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/injector/ScreenCaptureRunnable.java
@@ -7,11 +7,12 @@
import com.github.xsavikx.androidscreencast.api.image.ImageUtils;
import com.github.xsavikx.androidscreencast.api.recording.QuickTimeOutputStream;
import com.github.xsavikx.androidscreencast.exception.IORuntimeException;
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
@@ -20,49 +21,51 @@
import java.nio.channels.ClosedByInterruptException;
import java.util.concurrent.TimeUnit;
-@Component
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.ADB_COMMAND_TIMEOUT_KEY;
+
+@Singleton
public class ScreenCaptureRunnable implements Runnable {
- private static final Logger LOGGER = Logger.getLogger(ScreenCaptureRunnable.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ScreenCaptureRunnable.class);
private static final int MOV_FPS = 30;
private static final float MOV_COMPRESSION_RATE = 1f;
private static final int FRAME_DURATION = 10;
private final IDevice device;
+ private final long defaultAdbCommandTimeout;
private Dimension size;
private QuickTimeOutputStream qos = null;
private boolean landscape = false;
private ScreenCaptureListener listener = null;
- @Value("${adb.command.timeout:5}")
- private long defaultAdbCommandTimeout;
- @Value("${adb.command.timeout:5}")
private long currentAdbCommandTimeout;
private boolean isStopped = false;
- @Autowired
- public ScreenCaptureRunnable(IDevice device) {
- size = new Dimension();
+ @Inject
+ public ScreenCaptureRunnable(final IDevice device, @Named(ADB_COMMAND_TIMEOUT_KEY) long adbCommandTimeout) {
+ this.size = new Dimension();
this.device = device;
+ this.defaultAdbCommandTimeout = adbCommandTimeout;
+ this.currentAdbCommandTimeout = defaultAdbCommandTimeout;
}
@Override
public void run() {
- LOGGER.info("Starting ScreenCaptureRunnable");
+ LOGGER.info("Starting screen capturing");
while (!isStopped) {
try {
- RawImage screenshot = getScreenshot();
+ final RawImage screenshot = getScreenshot();
if (screenshot != null) {
display(screenshot);
} else {
- LOGGER.info("Failed to get device screenshot.");
+ LOGGER.info("Failed to get device screenshot");
}
- } catch (ClosedByInterruptException e) {
+ } catch (final ClosedByInterruptException e) {
LOGGER.error("ADB Channel closed due to interrupted exception", e);
break;
- } catch (InterruptedException e) {
+ } catch (final InterruptedException e) {
LOGGER.error("Execution of thread was interrupted. Shutting down thread.", e);
break;
}
}
- LOGGER.info("ScreenCaptureRunnable is stopped.");
+ LOGGER.info("Stopping screen capturing");
}
private RawImage getScreenshot() throws InterruptedException, ClosedByInterruptException {
@@ -74,7 +77,7 @@ private RawImage getScreenshot() throws InterruptedException, ClosedByInterruptE
currentAdbCommandTimeout = defaultAdbCommandTimeout;
} catch (TimeoutException e) {
currentAdbCommandTimeout++;
- LOGGER.warn(String.format("Adb command timeout happened. Timeout would be set to %d for the next try.", currentAdbCommandTimeout), e);
+ LOGGER.warn("Adb command timeout happened. Timeout would be set to {} for the next try.", currentAdbCommandTimeout, e);
} catch (AdbCommandRejectedException e) {
LOGGER.warn("ADB Command was rejected. Will try again in 100 ms.");
Thread.sleep(100);
@@ -87,9 +90,9 @@ private RawImage getScreenshot() throws InterruptedException, ClosedByInterruptE
return rawImage;
}
- private void display(RawImage rawImage) {
- RawImage imageToProcess = landscape ? rawImage.getRotated() : rawImage;
- BufferedImage image = ImageUtils.convertImage(imageToProcess);
+ private void display(final RawImage rawImage) {
+ final RawImage imageToProcess = landscape ? rawImage.getRotated() : rawImage;
+ final BufferedImage image = ImageUtils.convertImage(imageToProcess);
size.setSize(image.getWidth(), image.getHeight());
if (listener != null) {
SwingUtilities.invokeLater(() -> listener.handleNewImage(size, image, landscape));
@@ -99,25 +102,25 @@ private void display(RawImage rawImage) {
try {
qos.writeFrame(image, FRAME_DURATION);
} catch (IORuntimeException e) {
- LOGGER.error(e);
+ LOGGER.error("IO exception during writing video frame happened", e);
}
});
}
}
- public void setListener(ScreenCaptureListener listener) {
+ public void setListener(final ScreenCaptureListener listener) {
this.listener = listener;
}
- public void startRecording(File file) {
+ public void startRecording(final File file) {
try {
qos = new QuickTimeOutputStream(file, QuickTimeOutputStream.VideoFormat.JPG);
- } catch (IOException e) {
+ qos.setVideoCompressionQuality(MOV_COMPRESSION_RATE);
+ qos.setTimeScale(MOV_FPS);
+ } catch (final IOException e) {
throw new IORuntimeException(e);
}
- qos.setVideoCompressionQuality(MOV_COMPRESSION_RATE);
- qos.setTimeScale(MOV_FPS);
}
public void stopRecording() {
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/api/recording/atom/DataAtom.java b/src/main/java/com/github/xsavikx/androidscreencast/api/recording/atom/DataAtom.java
index f4927b2..759f3d8 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/api/recording/atom/DataAtom.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/api/recording/atom/DataAtom.java
@@ -5,6 +5,8 @@
import com.github.xsavikx.androidscreencast.api.recording.exception.MaximumAtomSizeExeededException;
import com.github.xsavikx.androidscreencast.exception.IORuntimeException;
import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.imageio.stream.ImageOutputStream;
import java.io.IOException;
@@ -13,6 +15,7 @@
* Data Atom.
*/
public class DataAtom extends CommonAtom {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DataAtom.class);
private static final int HEADER_SIZE = 1;
protected final DataAtomOutputStream data;
@@ -49,7 +52,7 @@ public void finish() {
finished = true;
long sizeAfter = size();
if (sizeBefore != sizeAfter) {
- System.err.println("size mismatch " + sizeBefore + ".." + sizeAfter);
+ LOGGER.warn("Size mismatch. sizeBefore={}, sizeAfter={}.", sizeBefore, sizeAfter);
}
}
} catch (IOException e) {
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/app/AndroidScreencastApplication.java b/src/main/java/com/github/xsavikx/androidscreencast/app/AndroidScreencastApplication.java
index c5c73ea..306b468 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/app/AndroidScreencastApplication.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/app/AndroidScreencastApplication.java
@@ -1,84 +1,67 @@
package com.github.xsavikx.androidscreencast.app;
-import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
+import com.github.xsavikx.androidscreencast.api.adb.AndroidDebugBridgeWrapper;
import com.github.xsavikx.androidscreencast.api.injector.Injector;
+import com.github.xsavikx.androidscreencast.configuration.ApplicationConfiguration;
import com.github.xsavikx.androidscreencast.ui.JFrameMain;
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import javax.swing.*;
import java.awt.*;
-@Component
+@Singleton
public class AndroidScreencastApplication extends SwingApplication {
- private static final Logger LOGGER = Logger.getLogger(AndroidScreencastApplication.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(AndroidScreencastApplication.class);
private final JFrameMain jFrameMain;
private final Injector injector;
private final IDevice iDevice;
- @Value("${adb.path}")
- private String adbPath;
+ private final AndroidDebugBridgeWrapper wrapper;
private transient boolean isStopped = false;
- @Autowired
- public AndroidScreencastApplication(Injector injector, IDevice iDevice, JFrameMain jFrameMain) {
+ @Inject
+ public AndroidScreencastApplication(final Injector injector, final IDevice iDevice, final JFrameMain jFrameMain,
+ final ApplicationConfiguration applicationConfiguration, AndroidDebugBridgeWrapper wrapper) {
+ super(applicationConfiguration);
this.injector = injector;
this.iDevice = iDevice;
this.jFrameMain = jFrameMain;
+ this.wrapper = wrapper;
}
@Override
public void stop() {
- try {
- LOGGER.debug("stop() - start");
- if (isStopped) {
- LOGGER.debug("Application is already stopped.");
- return;
- }
- if (injector != null)
- injector.stop();
-
- if (iDevice != null) {
- synchronized (iDevice) {
- if (hasFilledAdbPath())
- AndroidDebugBridge.disconnectBridge();
- AndroidDebugBridge.terminate();
- }
- }
- for (Frame frame : Frame.getFrames()) {
- frame.dispose();
- }
- isStopped = true;
- } finally {
- LOGGER.debug("stop() - end");
+ LOGGER.info("Stopping application");
+ if (isStopped) {
+ LOGGER.debug("Application is already stopped.");
+ return;
}
-
+ injector.stop();
+ wrapper.stop();
+ for (final Frame frame : Frame.getFrames()) {
+ frame.dispose();
+ }
+ isStopped = true;
}
@Override
public void start() {
- LOGGER.debug("start() - start");
+ LOGGER.info("Starting application");
if (iDevice == null) {
LOGGER.warn("No valid device was chosen. Please try to chose correct one.");
stop();
}
SwingUtilities.invokeLater(() -> {
+ jFrameMain.initialize();
// Start showing the iDevice screen
- jFrameMain.setTitle("" + iDevice);
-
+ jFrameMain.setTitle(iDevice.getSerialNumber());
// Show window
jFrameMain.setVisible(true);
jFrameMain.launchInjector();
});
- LOGGER.debug("start() - end");
- }
-
-
- private boolean hasFilledAdbPath() {
- return !StringUtils.isEmpty(adbPath);
}
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/app/DeviceChooserApplication.java b/src/main/java/com/github/xsavikx/androidscreencast/app/DeviceChooserApplication.java
index 1a34925..f2b89a9 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/app/DeviceChooserApplication.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/app/DeviceChooserApplication.java
@@ -1,87 +1,82 @@
package com.github.xsavikx.androidscreencast.app;
-import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
+import com.github.xsavikx.androidscreencast.api.adb.AndroidDebugBridgeWrapper;
+import com.github.xsavikx.androidscreencast.configuration.ApplicationConfiguration;
import com.github.xsavikx.androidscreencast.exception.NoDeviceChosenException;
import com.github.xsavikx.androidscreencast.exception.WaitDeviceListTimeoutException;
import com.github.xsavikx.androidscreencast.ui.JDialogDeviceList;
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-@Component
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationProperty.ADB_DEVICE_TIMEOUT;
+
+@Singleton
public class DeviceChooserApplication extends SwingApplication {
- private static final Logger LOGGER = Logger.getLogger(DeviceChooserApplication.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(DeviceChooserApplication.class);
private static final long WAIT_TIMEOUT = 100;
- private final AndroidDebugBridge bridge;
+ private final AndroidDebugBridgeWrapper bridge;
private final long adbWaitSleepCyclesAmount;
- @Value("${adb.device.timeout:30}")
- private long adbDeviceTimeout;
private IDevice device;
- @Autowired
- public DeviceChooserApplication(AndroidDebugBridge bridge) {
+ @Inject
+ public DeviceChooserApplication(final AndroidDebugBridgeWrapper bridge,
+ final ApplicationConfiguration applicationConfiguration) {
+ super(applicationConfiguration);
this.bridge = bridge;
- this.adbWaitSleepCyclesAmount = adbDeviceTimeout * 10;
+ this.adbWaitSleepCyclesAmount = getAdbDeviceTimeout() * 10;
+ }
+
+ private long getAdbDeviceTimeout() {
+ return Long.valueOf(applicationConfiguration.getProperty(ADB_DEVICE_TIMEOUT));
}
@Override
public void stop() {
- // ignore
+ bridge.stop();
}
@Override
public void start() {
- LOGGER.debug("start() - start");
- initialize();
- LOGGER.debug("start() - end");
- }
-
- private void waitDeviceList(AndroidDebugBridge bridge) {
- LOGGER.debug("waitDeviceList(AndroidDebugBridge bridge=" + bridge + ") - start");
-
- int count = 0;
- while (!bridge.hasInitialDeviceList()) {
- try {
- Thread.sleep(WAIT_TIMEOUT);
- count++;
- } catch (InterruptedException e) {
- LOGGER.warn("waitDeviceList(AndroidDebugBridge) - exception ignored", e);
-
- }
-
- if (count > adbWaitSleepCyclesAmount) {
- throw new WaitDeviceListTimeoutException();
- }
- }
-
- LOGGER.debug("waitDeviceList(AndroidDebugBridge bridge=" + bridge + ") - end");
- }
-
- private void initialize() {
- LOGGER.debug("initialize() - start");
+ LOGGER.info("Starting application");
waitDeviceList(bridge);
- IDevice devices[] = bridge.getDevices();
+ final IDevice devices[] = bridge.getDevices();
+
// Let the user choose the device
if (devices.length == 1) {
device = devices[0];
+ LOGGER.info("1 device was found by ADB");
} else {
- JDialogDeviceList jd = new JDialogDeviceList(devices);
+ final JDialogDeviceList jd = new JDialogDeviceList(devices);
jd.setVisible(true);
-
device = jd.getDevice();
- if (device == null) {
- return;
- }
+ LOGGER.info("{} devices were found by ADB", devices.length);
}
if (device == null) {
throw new NoDeviceChosenException();
}
- LOGGER.debug("initialize() - end");
+ LOGGER.info("{} was chosen", device.getName());
+ }
+
+ private void waitDeviceList(final AndroidDebugBridgeWrapper bridge) {
+ int count = 0;
+ while (!bridge.hasInitialDeviceList()) {
+ try {
+ Thread.sleep(WAIT_TIMEOUT);
+ count++;
+ } catch (InterruptedException e) {
+ LOGGER.warn("waitDeviceList(AndroidDebugBridge) - exception ignored", e);
+ }
+ if (count > adbWaitSleepCyclesAmount) {
+ throw new WaitDeviceListTimeoutException();
+ }
+ }
}
public IDevice getDevice() {
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/app/GUIApplication.java b/src/main/java/com/github/xsavikx/androidscreencast/app/GUIApplication.java
index 19e6fc7..52d24cf 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/app/GUIApplication.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/app/GUIApplication.java
@@ -1,15 +1,18 @@
package com.github.xsavikx.androidscreencast.app;
-public abstract class GUIApplication implements Application {
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
- public GUIApplication() {
- Runtime.getRuntime().addShutdownHook(new Thread(GUIApplication.this::stop));
+abstract class GUIApplication implements Application {
+ private static final Logger LOGGER = LoggerFactory.getLogger(GUIApplication.class);
+
+ GUIApplication() {
+ Runtime.getRuntime().addShutdownHook(new Thread(this::stop));
Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> {
try {
handleException(thread, ex);
- } catch (Exception ex2) {
- // ignored
- ex2.printStackTrace();
+ } catch (final Exception ex2) {
+ LOGGER.error("Error occurred during exception handling.", ex2);
}
});
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/app/SwingApplication.java b/src/main/java/com/github/xsavikx/androidscreencast/app/SwingApplication.java
index 1a19362..d3d80a3 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/app/SwingApplication.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/app/SwingApplication.java
@@ -1,20 +1,29 @@
package com.github.xsavikx.androidscreencast.app;
+import com.github.xsavikx.androidscreencast.configuration.ApplicationConfiguration;
import com.github.xsavikx.androidscreencast.exception.AndroidScreenCastRuntimeException;
import com.github.xsavikx.androidscreencast.ui.JDialogError;
-import org.springframework.beans.factory.annotation.Value;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.io.PrintWriter;
import java.io.StringWriter;
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationProperty.APP_NATIVE_LOOK;
+
public abstract class SwingApplication extends GUIApplication {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DeviceChooserApplication.class);
+ private static final String SYNC_TREE_UI = "SynthTreeUI";
+ protected final ApplicationConfiguration applicationConfiguration;
private JDialogError jd = null;
- @Value("${app.native.look:true}")
- private boolean nativeLook;
+
+ protected SwingApplication(final ApplicationConfiguration applicationConfiguration) {
+ this.applicationConfiguration = applicationConfiguration;
+ }
private boolean useNativeLook() {
- return nativeLook;
+ return Boolean.valueOf(applicationConfiguration.getProperty(APP_NATIVE_LOOK));
}
@Override
@@ -28,19 +37,21 @@ public void init() {
}
@Override
- public void handleException(Thread thread, Throwable ex) {
+ public void handleException(final Thread thread, final Throwable ex) {
try {
- StringWriter sw = new StringWriter();
+ final StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
- if (sw.toString().contains("SynthTreeUI"))
+ if (sw.toString().contains(SYNC_TREE_UI))
return;
- ex.printStackTrace(System.err);
+ LOGGER.error(ex.getClass().getSimpleName(), ex);
if (jd != null && jd.isVisible())
return;
jd = new JDialogError(ex);
- SwingUtilities.invokeLater(() -> jd.setVisible(true));
- } catch (Exception ignored) {
- // ignored
+ SwingUtilities.invokeLater(() -> {
+ jd.setVisible(true);
+ });
+ } catch (Exception e) {
+ LOGGER.warn("Exception occurred during exception handling.", e);
}
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfiguration.java b/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfiguration.java
new file mode 100644
index 0000000..5449143
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfiguration.java
@@ -0,0 +1,43 @@
+package com.github.xsavikx.androidscreencast.configuration;
+
+import com.github.xsavikx.androidscreencast.exception.AndroidScreenCastRuntimeException;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+@Singleton
+public class ApplicationConfiguration {
+ private static final String PROPERTIES_LOCATION = "./app.properties";
+ private final Properties properties;
+
+ @Inject
+ public ApplicationConfiguration() {
+ properties = initProperties();
+ }
+
+ private Properties initProperties() {
+ final Properties properties = new Properties();
+ loadProperties(properties, PROPERTIES_LOCATION);
+ return properties;
+ }
+
+ private void loadProperties(final Properties properties, final String propertiesLocation) {
+ final File propertiesFile = new File(propertiesLocation);
+ if (propertiesFile.exists()) {
+ try (final FileInputStream fis = new FileInputStream(propertiesFile)) {
+ properties.load(fis);
+ } catch (final IOException e) {
+ throw new AndroidScreenCastRuntimeException(e);
+ }
+ }
+ }
+
+ public String getProperty(final ApplicationConfigurationProperty configurationProperty) {
+ final String property = properties.getProperty(configurationProperty.getPropertyKey(), configurationProperty.getDefaultValue());
+ return property;
+ }
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfigurationProperty.java b/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfigurationProperty.java
new file mode 100644
index 0000000..25e1fa1
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfigurationProperty.java
@@ -0,0 +1,27 @@
+package com.github.xsavikx.androidscreencast.configuration;
+
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.*;
+
+public enum ApplicationConfigurationProperty {
+ ADB_PATH(ADB_PATH_KEY, ""),
+ ADB_DEVICE_TIMEOUT(ADB_DEVICE_TIMEOUT_KEY, "30"),
+ ADB_COMMAND_TIMEOUT(ADB_COMMAND_TIMEOUT_KEY, "5"),
+ APP_WINDOW_WIDTH(APP_WINDOW_WIDTH_KEY, "1024"),
+ APP_WINDOW_HEIGHT(APP_WINDOW_HEIGHT_KEY, "768"),
+ APP_NATIVE_LOOK(APP_NATIVE_LOOK_KEY, "true");
+ private final String propertyKey;
+ private final String defaultValue;
+
+ ApplicationConfigurationProperty(final String propertyKey, String defaultValue) {
+ this.propertyKey = propertyKey;
+ this.defaultValue = defaultValue;
+ }
+
+ public String getPropertyKey() {
+ return propertyKey;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfigurationPropertyKeys.java b/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfigurationPropertyKeys.java
new file mode 100644
index 0000000..32c489c
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/configuration/ApplicationConfigurationPropertyKeys.java
@@ -0,0 +1,14 @@
+package com.github.xsavikx.androidscreencast.configuration;
+
+public final class ApplicationConfigurationPropertyKeys {
+ public static final String ADB_PATH_KEY = "adb.path";
+ public static final String ADB_DEVICE_TIMEOUT_KEY = "adb.device.timeout";
+ public static final String ADB_COMMAND_TIMEOUT_KEY = "adb.command.timeout";
+ public static final String APP_WINDOW_WIDTH_KEY = "app.window.width";
+ public static final String APP_WINDOW_HEIGHT_KEY = "app.window.height";
+ public static final String APP_NATIVE_LOOK_KEY = "app.native.look";
+
+ private ApplicationConfigurationPropertyKeys() {
+ //
+ }
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/constant/Constants.java b/src/main/java/com/github/xsavikx/androidscreencast/constant/Constants.java
deleted file mode 100644
index 99f06d3..0000000
--- a/src/main/java/com/github/xsavikx/androidscreencast/constant/Constants.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.github.xsavikx.androidscreencast.constant;
-
-import javax.annotation.Resource;
-
-@Resource
-public final class Constants {
- public static final String APP_NATIVE_LOOK_PROPERTY = "app.native.look";
- public static final String ADB_PATH_PROPERTY = "adb.path";
- public static final String DEFAULT_WINDOW_WIDTH = "default.window.width";
- public static final String DEFAULT_WINDOW_HEIGHT = "default.window.height";
-}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/dagger/ApiModule.java b/src/main/java/com/github/xsavikx/androidscreencast/dagger/ApiModule.java
new file mode 100644
index 0000000..4e88110
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/dagger/ApiModule.java
@@ -0,0 +1,60 @@
+package com.github.xsavikx.androidscreencast.dagger;
+
+import com.github.xsavikx.androidscreencast.api.AndroidDevice;
+import com.github.xsavikx.androidscreencast.api.AndroidDeviceImpl;
+import com.github.xsavikx.androidscreencast.api.command.executor.CommandExecutor;
+import com.github.xsavikx.androidscreencast.api.command.executor.ShellCommandExecutor;
+import com.github.xsavikx.androidscreencast.api.command.factory.AdbInputCommandFactory;
+import com.github.xsavikx.androidscreencast.api.command.factory.InputCommandFactory;
+import com.github.xsavikx.androidscreencast.configuration.ApplicationConfiguration;
+import dagger.Module;
+import dagger.Provides;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationProperty.*;
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.*;
+
+@Singleton
+@Module
+public class ApiModule {
+ @Singleton
+ @Named(ADB_COMMAND_TIMEOUT_KEY)
+ @Provides
+ public static long adbCommandTimeout(ApplicationConfiguration applicationConfiguration) {
+ return Long.valueOf(applicationConfiguration.getProperty(ADB_COMMAND_TIMEOUT));
+ }
+
+ @Singleton
+ @Named(ADB_DEVICE_TIMEOUT_KEY)
+ @Provides
+ public static long adbDeviceTimeout(ApplicationConfiguration applicationConfiguration) {
+ return Long.valueOf(applicationConfiguration.getProperty(ADB_DEVICE_TIMEOUT));
+ }
+
+ @Singleton
+ @Named(ADB_PATH_KEY)
+ @Provides
+ public static String adbPath(ApplicationConfiguration applicationConfiguration) {
+ return applicationConfiguration.getProperty(ADB_PATH);
+ }
+
+ @Singleton
+ @Provides
+ public static CommandExecutor commandExecutor(ShellCommandExecutor shellCommandExecutor) {
+ return shellCommandExecutor;
+ }
+
+ @Singleton
+ @Provides
+ public static AndroidDevice androidDevice(AndroidDeviceImpl androidDevice) {
+ return androidDevice;
+ }
+
+ @Singleton
+ @Provides
+ public static InputCommandFactory inputCommandFactory(AdbInputCommandFactory adbInputCommandFactory) {
+ return adbInputCommandFactory;
+ }
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/dagger/AppModule.java b/src/main/java/com/github/xsavikx/androidscreencast/dagger/AppModule.java
new file mode 100644
index 0000000..0672b8d
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/dagger/AppModule.java
@@ -0,0 +1,34 @@
+package com.github.xsavikx.androidscreencast.dagger;
+
+import com.android.ddmlib.IDevice;
+import com.github.xsavikx.androidscreencast.app.AndroidScreencastApplication;
+import com.github.xsavikx.androidscreencast.app.Application;
+import com.github.xsavikx.androidscreencast.app.DeviceChooserApplication;
+import dagger.Module;
+import dagger.Provides;
+
+import javax.inject.Singleton;
+
+@Singleton
+@Module
+public class AppModule {
+ @Singleton
+ @Provides
+ public static Application application(AndroidScreencastApplication application) {
+ return application;
+ }
+
+ @Singleton
+ @Provides
+ public static IDevice iDevice(final DeviceChooserApplication application) {
+ try {
+ application.init();
+ application.start();
+ IDevice device = application.getDevice();
+ return device;
+ } catch (Throwable e) {
+ application.stop();
+ throw e;
+ }
+ }
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/dagger/MainComponent.java b/src/main/java/com/github/xsavikx/androidscreencast/dagger/MainComponent.java
new file mode 100644
index 0000000..b5ad021
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/dagger/MainComponent.java
@@ -0,0 +1,18 @@
+package com.github.xsavikx.androidscreencast.dagger;
+
+import com.github.xsavikx.androidscreencast.api.command.executor.CommandExecutor;
+import com.github.xsavikx.androidscreencast.api.command.factory.InputCommandFactory;
+import com.github.xsavikx.androidscreencast.app.Application;
+import dagger.Component;
+
+import javax.inject.Singleton;
+
+@Singleton
+@Component(modules = {ApiModule.class, AppModule.class, UiModule.class})
+public interface MainComponent {
+ Application application();
+
+ CommandExecutor commandExecutor();
+
+ InputCommandFactory inputCommandFactory();
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/dagger/MainComponentProvider.java b/src/main/java/com/github/xsavikx/androidscreencast/dagger/MainComponentProvider.java
new file mode 100644
index 0000000..27f42f1
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/dagger/MainComponentProvider.java
@@ -0,0 +1,16 @@
+package com.github.xsavikx.androidscreencast.dagger;
+
+public final class MainComponentProvider {
+ private static MainComponent INSTANCE;
+
+ private MainComponentProvider() {
+
+ }
+
+ public static MainComponent mainComponent() {
+ if (INSTANCE == null) {
+ INSTANCE = DaggerMainComponent.create();
+ }
+ return INSTANCE;
+ }
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/dagger/UiModule.java b/src/main/java/com/github/xsavikx/androidscreencast/dagger/UiModule.java
new file mode 100644
index 0000000..f3f460b
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/dagger/UiModule.java
@@ -0,0 +1,37 @@
+package com.github.xsavikx.androidscreencast.dagger;
+
+import com.github.xsavikx.androidscreencast.api.injector.InputKeyEvent;
+import com.github.xsavikx.androidscreencast.configuration.ApplicationConfiguration;
+import com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationProperty;
+import dagger.Module;
+import dagger.Provides;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.APP_WINDOW_HEIGHT_KEY;
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.APP_WINDOW_WIDTH_KEY;
+
+@Singleton
+@Module
+public class UiModule {
+ @Singleton
+ @Named(APP_WINDOW_WIDTH_KEY)
+ @Provides
+ public static int appWindowHeight(final ApplicationConfiguration applicationConfiguration) {
+ return Integer.valueOf(applicationConfiguration.getProperty(ApplicationConfigurationProperty.APP_WINDOW_HEIGHT));
+ }
+
+ @Singleton
+ @Named(APP_WINDOW_HEIGHT_KEY)
+ @Provides
+ public static int appWindowWidth(final ApplicationConfiguration applicationConfiguration) {
+ return Integer.valueOf(applicationConfiguration.getProperty(ApplicationConfigurationProperty.APP_WINDOW_WIDTH));
+ }
+
+ @Singleton
+ @Provides
+ public static InputKeyEvent[] initialData() {
+ return InputKeyEvent.values();
+ }
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/exception/IllegalAdbConfigurationException.java b/src/main/java/com/github/xsavikx/androidscreencast/exception/IllegalAdbConfigurationException.java
new file mode 100644
index 0000000..7c13535
--- /dev/null
+++ b/src/main/java/com/github/xsavikx/androidscreencast/exception/IllegalAdbConfigurationException.java
@@ -0,0 +1,10 @@
+package com.github.xsavikx.androidscreencast.exception;
+
+/**
+ * Created by User on 16.02.2017.
+ */
+public class IllegalAdbConfigurationException extends AndroidScreenCastRuntimeException {
+ public IllegalAdbConfigurationException(String adbPath) {
+ super(String.format("Exception happened during running your ADB instance. Probably ADB path is misconfigured. ADB path='%s'", adbPath));
+ }
+}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/spring/config/ApplicationConfiguration.java b/src/main/java/com/github/xsavikx/androidscreencast/spring/config/ApplicationConfiguration.java
deleted file mode 100644
index 27d4f62..0000000
--- a/src/main/java/com/github/xsavikx/androidscreencast/spring/config/ApplicationConfiguration.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.github.xsavikx.androidscreencast.spring.config;
-
-import com.android.ddmlib.AndroidDebugBridge;
-import com.android.ddmlib.IDevice;
-import com.github.xsavikx.androidscreencast.app.DeviceChooserApplication;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.context.annotation.*;
-import org.springframework.util.StringUtils;
-
-import javax.annotation.PreDestroy;
-
-@Configuration
-@ComponentScan(basePackages = "com.github.xsavikx.androidscreencast")
-@PropertySources(value = {
- @PropertySource(value = "file:${user.dir}/app.properties", ignoreResourceNotFound = true)
-})
-public class ApplicationConfiguration {
- @Value("${adb.path}")
- private String adbPath;
-
- @Bean
- public AndroidDebugBridge initAndroidDebugBridge() {
- AndroidDebugBridge.initIfNeeded(false);
- if (!StringUtils.isEmpty(adbPath)) {
- return AndroidDebugBridge.createBridge(adbPath, false);
- }
- return AndroidDebugBridge.createBridge();
- }
-
- @PreDestroy
- public void preDestroy() {
- AndroidDebugBridge.disconnectBridge();
- AndroidDebugBridge.terminate();
- }
-
- @Bean
- public DefaultListableBeanFactory initBeanFactory() {
- return new DefaultListableBeanFactory();
- }
-
- @Bean
- @Autowired
- public IDevice initDevice(DeviceChooserApplication application) {
- application.init();
- application.start();
- application.stop();
- return application.getDevice();
- }
-
-}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/spring/config/ApplicationContextProvider.java b/src/main/java/com/github/xsavikx/androidscreencast/spring/config/ApplicationContextProvider.java
deleted file mode 100644
index 68c0c1c..0000000
--- a/src/main/java/com/github/xsavikx/androidscreencast/spring/config/ApplicationContextProvider.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.github.xsavikx.androidscreencast.spring.config;
-
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.annotation.AnnotationConfigApplicationContext;
-
-public class ApplicationContextProvider implements ApplicationContextAware {
- private static ApplicationContext applicationContext;
-
- private ApplicationContextProvider() {
- //
- }
-
- public static ApplicationContext getApplicationContext() {
- if (applicationContext == null)
- applicationContext = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
- return applicationContext;
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- ApplicationContextProvider.applicationContext = applicationContext;
- }
-
- public static T getBean(Class clazz) throws BeansException {
- return getApplicationContext().getBean(clazz);
- }
-
-}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/ui/JDialogError.java b/src/main/java/com/github/xsavikx/androidscreencast/ui/JDialogError.java
index 171518c..8d5435a 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/ui/JDialogError.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/ui/JDialogError.java
@@ -2,6 +2,7 @@
import com.github.xsavikx.androidscreencast.exception.AndroidScreenCastRuntimeException;
import com.github.xsavikx.androidscreencast.exception.IORuntimeException;
+import com.github.xsavikx.androidscreencast.util.StringUtils;
import javax.swing.*;
import java.awt.*;
@@ -53,10 +54,13 @@ private void setErrorDetails(Throwable e) {
AndroidScreenCastRuntimeException realCause = getCause(ex);
if (realCause != null) {
errorDialogLabel.setText(realCause.getClass().getSimpleName());
- stringWriter.append(realCause.getMessage()).append('\n').append('\n');
- stringWriter.append(realCause.getAdditionalInformation());
+ if (StringUtils.isNotEmpty(realCause.getMessage()))
+ stringWriter.append(realCause.getMessage()).append('\n').append('\n');
+ if (StringUtils.isNotEmpty(realCause.getAdditionalInformation()))
+ stringWriter.append(realCause.getAdditionalInformation());
} else {
- stringWriter.append(ex.getMessage()).append('\n').append('\n');
+ if (StringUtils.isNotEmpty(ex.getMessage()))
+ stringWriter.append(ex.getMessage()).append('\n').append('\n');
ex.printStackTrace(new PrintWriter(stringWriter));
}
errorDescription.setText(stringWriter.toString());
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/ui/JDialogExecuteKeyEvent.java b/src/main/java/com/github/xsavikx/androidscreencast/ui/JDialogExecuteKeyEvent.java
index d4eb5c5..80e348d 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/ui/JDialogExecuteKeyEvent.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/ui/JDialogExecuteKeyEvent.java
@@ -1,19 +1,18 @@
package com.github.xsavikx.androidscreencast.ui;
+import com.github.xsavikx.androidscreencast.api.command.KeyCommand;
import com.github.xsavikx.androidscreencast.api.command.executor.CommandExecutor;
-import com.github.xsavikx.androidscreencast.api.command.factory.AdbInputCommandFactory;
+import com.github.xsavikx.androidscreencast.api.command.factory.InputCommandFactory;
import com.github.xsavikx.androidscreencast.api.injector.InputKeyEvent;
import com.github.xsavikx.androidscreencast.ui.model.InputKeyEventTable;
-import com.github.xsavikx.androidscreencast.ui.model.InputKeyEventTableModel;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
-@Component
+@Singleton
public class JDialogExecuteKeyEvent extends JDialog {
private static final long serialVersionUID = -4152020879675916776L;
private static final int HEIGHT = 600;
@@ -22,7 +21,7 @@ public class JDialogExecuteKeyEvent extends JDialog {
private static final int BUTTON_WIDTH = WIDTH >> 1 - 5;
private static final int TITLE_COLUMN_INDEX = 1;
-
+ private static final String TITLE = "Execute key event";
private static final String EXECUTE_BUTTON_TEXT = "Execute";
private static final String USE_LONG_PRESS_BUTTON_TEXT = "Long press";
private static final String CANCEL_BUTTON_TEXT = "Cancel";
@@ -31,20 +30,26 @@ public class JDialogExecuteKeyEvent extends JDialog {
private static final String NO_COMMAND_CHOSEN_WARNING_DIALOG_TITLE = "Warning";
private final CommandExecutor commandExecutor;
+ private final InputKeyEventTable commandListTable;
+ private final InputCommandFactory inputCommandFactory;
- @Autowired
- public JDialogExecuteKeyEvent(CommandExecutor commandExecutor) {
+ @Inject
+ public JDialogExecuteKeyEvent(CommandExecutor commandExecutor, InputKeyEventTable commandListTable, InputCommandFactory inputCommandFactory) {
this.commandExecutor = commandExecutor;
+ this.commandListTable = commandListTable;
+ this.inputCommandFactory = inputCommandFactory;
+ init();
}
+ public void open() {
+ setVisible(true);
+ }
- @PostConstruct
- private void initialize() {
- setResizable(false);
- setTitle("Execute key event");
+ private void init() {
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
- final InputKeyEventTableModel commandList = new InputKeyEventTableModel(InputKeyEvent.values());
- final InputKeyEventTable commandListTable = new InputKeyEventTable(commandList);
+ setResizable(false);
+ setTitle(TITLE);
+ setAlwaysOnTop(true);
final JCheckBoxMenuItem useLongPress = new JCheckBoxMenuItem(USE_LONG_PRESS_BUTTON_TEXT, false);
JButton executeCommandButton = new JButton(EXECUTE_BUTTON_TEXT);
@@ -52,9 +57,14 @@ private void initialize() {
executeCommandButton.addActionListener(actionEvent -> {
int rowIndex = commandListTable.getSelectedRow();
if (rowIndex > 0) {
- final String title = (String) commandList.getValueAt(rowIndex, TITLE_COLUMN_INDEX);
- SwingUtilities.invokeLater(() -> commandExecutor.execute(AdbInputCommandFactory.getKeyCommand(InputKeyEvent.valueOf(title),
- useLongPress.getState())));
+
+ final String title = (String) commandListTable.getModel().getValueAt(rowIndex, TITLE_COLUMN_INDEX);
+ SwingUtilities.invokeLater(() -> {
+ final InputKeyEvent inputKeyEvent = InputKeyEvent.valueOf(title);
+ final boolean longPress = useLongPress.getState();
+ final KeyCommand keyCommand = inputCommandFactory.getKeyCommand(inputKeyEvent, longPress);
+ commandExecutor.execute(keyCommand);
+ });
closeDialog();
} else {
JOptionPane.showMessageDialog(null, NO_COMMAND_CHOSEN_WARNING_MESSAGE, NO_COMMAND_CHOSEN_WARNING_DIALOG_TITLE,
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/ui/JFrameMain.java b/src/main/java/com/github/xsavikx/androidscreencast/ui/JFrameMain.java
index 4672886..768fd26 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/ui/JFrameMain.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/ui/JFrameMain.java
@@ -2,36 +2,38 @@
import com.github.xsavikx.androidscreencast.api.injector.Injector;
import com.github.xsavikx.androidscreencast.api.injector.InputKeyEvent;
-import com.github.xsavikx.androidscreencast.app.AndroidScreencastApplication;
-import com.github.xsavikx.androidscreencast.constant.Constants;
+import com.github.xsavikx.androidscreencast.dagger.MainComponentProvider;
import com.github.xsavikx.androidscreencast.exception.IORuntimeException;
-import com.github.xsavikx.androidscreencast.spring.config.ApplicationContextProvider;
import com.github.xsavikx.androidscreencast.ui.explorer.JFrameExplorer;
import com.github.xsavikx.androidscreencast.ui.interaction.KeyEventDispatcherFactory;
import com.github.xsavikx.androidscreencast.ui.interaction.KeyboardActionListenerFactory;
+import com.github.xsavikx.androidscreencast.ui.interaction.MouseActionAdapter;
import com.google.common.io.Files;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.env.Environment;
-import org.springframework.stereotype.Component;
-import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
-@Component
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.APP_WINDOW_HEIGHT_KEY;
+import static com.github.xsavikx.androidscreencast.configuration.ApplicationConfigurationPropertyKeys.APP_WINDOW_WIDTH_KEY;
+
+@Singleton
public class JFrameMain extends JFrame {
private static final long serialVersionUID = -2085909236767692371L;
private final JPanelScreen jp;
- private final MouseAdapter ma;
+ private final MouseActionAdapter ma;
private final Injector injector;
- private final Environment env;
+ private final Dimension windowSize;
+ private final JFrameExplorer frameExplorer;
+ private final JDialogExecuteKeyEvent dialogExecuteKeyEvent;
private transient boolean isDisposed = false;
private JToolBar jtb = new JToolBar();
private JToolBar jtbHardkeys = new JToolBar();
@@ -47,22 +49,16 @@ public class JFrameMain extends JFrame {
private JButton jbRecord = new JButton("Start record");
private Dimension oldImageDimension;
- @Autowired
- public JFrameMain(JPanelScreen jp, Environment env, Injector injector, MouseAdapter ma) {
+ @Inject
+ public JFrameMain(JPanelScreen jp, Injector injector, MouseActionAdapter ma,
+ JFrameExplorer frameExplorer, JDialogExecuteKeyEvent dialogExecuteKeyEvent, @Named(APP_WINDOW_WIDTH_KEY) int width,
+ @Named(APP_WINDOW_HEIGHT_KEY) int height) {
this.jp = jp;
this.injector = injector;
- this.env = env;
this.ma = ma;
- }
-
- private void setPreferredWindowSize() {
- if (env.containsProperty(Constants.DEFAULT_WINDOW_HEIGHT) && env.containsProperty(Constants.DEFAULT_WINDOW_WIDTH)) {
- Integer height = env.getProperty(Constants.DEFAULT_WINDOW_HEIGHT, Integer.class);
- Integer width = env.getProperty(Constants.DEFAULT_WINDOW_WIDTH, Integer.class);
- if (height != null && width != null)
- getContentPane().setPreferredSize(new Dimension(width, height));
- }
- pack();
+ this.frameExplorer = frameExplorer;
+ this.dialogExecuteKeyEvent = dialogExecuteKeyEvent;
+ this.windowSize = new Dimension(width, height);
}
@Override
@@ -72,10 +68,9 @@ public void dispose() {
}
isDisposed = true;
super.dispose();
- ApplicationContextProvider.getBean(AndroidScreencastApplication.class).stop();
+ MainComponentProvider.mainComponent().application().stop();
}
- @PostConstruct
public void initialize() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
KeyboardFocusManager.getCurrentKeyboardFocusManager()
@@ -107,7 +102,6 @@ public void initialize() {
jtbHardkeys.add(jbKbPhoneOn);
jtbHardkeys.add(jbKbPhoneOff);
- setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
add(jtb, BorderLayout.NORTH);
add(jtbHardkeys, BorderLayout.SOUTH);
@@ -123,23 +117,28 @@ public void initialize() {
jp.addMouseWheelListener(ma);
jbExplorer.addActionListener(actionEvent -> {
- JFrameExplorer jf = ApplicationContextProvider.getBean(JFrameExplorer.class);
- jf.setIconImage(getIconImage());
- jf.launch();
- jf.setVisible(true);
+ SwingUtilities.invokeLater(() -> {
+ JFrameExplorer jf = frameExplorer;
+ jf.setIconImage(getIconImage());
+ jf.launch();
+ jf.setVisible(true);
+ });
});
jtb.add(jbExplorer);
jbExecuteKeyEvent.addActionListener(actionEvent -> {
- JDialogExecuteKeyEvent jdExecuteKeyEvent = ApplicationContextProvider
- .getBean(JDialogExecuteKeyEvent.class);
- jdExecuteKeyEvent.setVisible(true);
+ SwingUtilities.invokeLater(dialogExecuteKeyEvent::open);
});
jtb.add(jbExecuteKeyEvent);
jtb.add(jbRecord);
}
+ private void setPreferredWindowSize() {
+ getContentPane().setPreferredSize(windowSize);
+ pack();
+ }
+
private ActionListener createRecordActionListener() {
return new ActionListener() {
private final Path tmpDir = Files.createTempDir().toPath();
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/ui/JPanelScreen.java b/src/main/java/com/github/xsavikx/androidscreencast/ui/JPanelScreen.java
index d6362a6..3006250 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/ui/JPanelScreen.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/ui/JPanelScreen.java
@@ -1,12 +1,12 @@
package com.github.xsavikx.androidscreencast.ui;
-import org.springframework.stereotype.Component;
-
+import javax.inject.Inject;
+import javax.inject.Singleton;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
-@Component
+@Singleton
public class JPanelScreen extends JPanel {
private static final long serialVersionUID = -2034873107028503004L;
private float coef = 1;
@@ -15,37 +15,40 @@ public class JPanelScreen extends JPanel {
private Dimension size = null;
private BufferedImage image = null;
+ @Inject
public JPanelScreen() {
- this.setFocusable(true);
+ setFocusable(true);
}
- public Point getRawPoint(Point p1) {
- Point p2 = new Point();
+ public Point getRawPoint(final Point p1) {
+ final Point p2 = new Point();
p2.x = (int) ((p1.x - origX) / coef);
p2.y = (int) ((p1.y - origY) / coef);
return p2;
}
- public void handleNewImage(Dimension size, BufferedImage image) {
+ public void handleNewImage(final Dimension size, final BufferedImage image) {
this.size = size;
this.image = image;
repaint();
}
@Override
- protected void paintComponent(Graphics g) {
- if (size == null)
- return;
- if (size.height == 0)
+ protected void paintComponent(final Graphics g) {
+ if (isNotInitialized())
return;
- Graphics2D g2 = (Graphics2D) g;
+ final Graphics2D g2 = (Graphics2D) g;
g2.clearRect(0, 0, getWidth(), getHeight());
- double width = Math.min(getWidth(), size.width * getHeight() / size.height);
+ final double width = Math.min(getWidth(), size.width * getHeight() / size.height);
coef = (float) width / size.width;
- double height = width * size.height / size.width;
+ final double height = width * size.height / size.width;
origX = (getWidth() - width) / 2;
origY = (getHeight() - height) / 2;
g2.drawImage(image, (int) origX, (int) origY, (int) width, (int) height, this);
}
+ private boolean isNotInitialized() {
+ return size == null || size.height == 0 || size.width == 0;
+ }
+
}
diff --git a/src/main/java/com/github/xsavikx/androidscreencast/ui/explorer/JFrameExplorer.java b/src/main/java/com/github/xsavikx/androidscreencast/ui/explorer/JFrameExplorer.java
index 41a7f0f..f40b571 100644
--- a/src/main/java/com/github/xsavikx/androidscreencast/ui/explorer/JFrameExplorer.java
+++ b/src/main/java/com/github/xsavikx/androidscreencast/ui/explorer/JFrameExplorer.java
@@ -3,9 +3,8 @@
import com.github.xsavikx.androidscreencast.api.AndroidDevice;
import com.github.xsavikx.androidscreencast.api.file.FileInfo;
import com.github.xsavikx.androidscreencast.exception.AndroidScreenCastRuntimeException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
+import javax.inject.Inject;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
@@ -19,7 +18,6 @@
import java.util.List;
import java.util.Map;
-@Component
public class JFrameExplorer extends JFrame {
private static final long serialVersionUID = -5209265873286028854L;
@@ -28,7 +26,7 @@ public class JFrameExplorer extends JFrame {
private JList