no message
This commit is contained in:
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@@ -10,6 +10,7 @@
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/lib" />
|
||||
<option value="$PROJECT_DIR$/shareandcontrollib" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
|
||||
98
.idea/misc.xml
generated
98
.idea/misc.xml
generated
@@ -3,6 +3,72 @@
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="MarkdownProjectSettings">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true">
|
||||
<PanelProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
</PanelProvider>
|
||||
</PreviewSettings>
|
||||
<ParserSettings>
|
||||
<PegdownExtensions>
|
||||
<option name="ABBREVIATIONS" value="false" />
|
||||
<option name="ANCHORLINKS" value="true" />
|
||||
<option name="ATXHEADERSPACE" value="true" />
|
||||
<option name="AUTOLINKS" value="true" />
|
||||
<option name="DEFINITIONS" value="false" />
|
||||
<option name="FENCED_CODE_BLOCKS" value="true" />
|
||||
<option name="FOOTNOTES" value="false" />
|
||||
<option name="HARDWRAPS" value="false" />
|
||||
<option name="INSERTED" value="false" />
|
||||
<option name="QUOTES" value="false" />
|
||||
<option name="RELAXEDHRULES" value="true" />
|
||||
<option name="SMARTS" value="false" />
|
||||
<option name="STRIKETHROUGH" value="true" />
|
||||
<option name="SUBSCRIPT" value="false" />
|
||||
<option name="SUPERSCRIPT" value="false" />
|
||||
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
|
||||
<option name="SUPPRESS_INLINE_HTML" value="false" />
|
||||
<option name="TABLES" value="true" />
|
||||
<option name="TASKLISTITEMS" value="true" />
|
||||
<option name="TOC" value="false" />
|
||||
<option name="WIKILINKS" value="true" />
|
||||
</PegdownExtensions>
|
||||
<ParserOptions>
|
||||
<option name="COMMONMARK_LISTS" value="false" />
|
||||
<option name="DUMMY" value="false" />
|
||||
<option name="EMOJI_SHORTCUTS" value="true" />
|
||||
<option name="FLEXMARK_FRONT_MATTER" value="false" />
|
||||
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="true" />
|
||||
<option name="GFM_TABLE_RENDERING" value="true" />
|
||||
<option name="GITBOOK_URL_ENCODING" value="false" />
|
||||
<option name="GITHUB_EMOJI_URL" value="false" />
|
||||
<option name="GITHUB_LISTS" value="true" />
|
||||
<option name="GITHUB_WIKI_LINKS" value="true" />
|
||||
<option name="JEKYLL_FRONT_MATTER" value="false" />
|
||||
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
|
||||
</ParserOptions>
|
||||
</ParserSettings>
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true">
|
||||
<GeneratorProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
|
||||
</GeneratorProvider>
|
||||
<headerTop />
|
||||
<headerBottom />
|
||||
<bodyTop />
|
||||
<bodyBottom />
|
||||
</HtmlSettings>
|
||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||
<StylesheetProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
|
||||
</StylesheetProvider>
|
||||
<ScriptProviders />
|
||||
<cssText />
|
||||
</CssSettings>
|
||||
<HtmlExportSettings updateOnSave="false" parentDir="$ProjectFileDir$" targetDir="$ProjectFileDir$" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" />
|
||||
<LinkMapSettings>
|
||||
<textMaps />
|
||||
</LinkMapSettings>
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
@@ -27,6 +93,38 @@
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectInspectionProfilesVisibleTreeState">
|
||||
<entry key="Project Default">
|
||||
<profile-state>
|
||||
<expanded-state>
|
||||
<State>
|
||||
<id />
|
||||
</State>
|
||||
<State>
|
||||
<id>Code style issuesJava</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Groovy</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Java</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Potentially confusing code constructsGroovy</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Probable bugsJava</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Serialization issuesJava</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Threading issuesJava</id>
|
||||
</State>
|
||||
</expanded-state>
|
||||
</profile-state>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
|
||||
3
.idea/modules.xml
generated
3
.idea/modules.xml
generated
@@ -2,9 +2,10 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/androidScreenShareAndControl.iml" filepath="$PROJECT_DIR$/androidScreenShareAndControl.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/lib/lib.iml" filepath="$PROJECT_DIR$/lib/lib.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/屏幕共享A.iml" filepath="$PROJECT_DIR$/屏幕共享A.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/shareandcontrollib/shareandcontrollib.iml" filepath="$PROJECT_DIR$/shareandcontrollib/shareandcontrollib.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -23,12 +23,14 @@ import javax.swing.border.EmptyBorder;
|
||||
|
||||
public class Client extends JFrame {
|
||||
JLabel label;
|
||||
boolean isMove = false;
|
||||
|
||||
public Client() throws IOException {
|
||||
setLayout(new BorderLayout(0, 0));
|
||||
|
||||
JPanel ipPanel = new JPanel(new BorderLayout(5, 5));
|
||||
final JTextField ipField = new JTextField();
|
||||
ipField.setText("127.0.0.1");
|
||||
ipPanel.add(ipField, BorderLayout.CENTER);
|
||||
ipPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
|
||||
@@ -53,8 +55,6 @@ public class Client extends JFrame {
|
||||
|
||||
label = new JLabel();
|
||||
|
||||
// Image image = ImageIO.read(new File("/Users/wanjian/Desktop/img.jpg"));
|
||||
// label.setIcon(new ImageIcon(image));
|
||||
label.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
add(panelContainer2, BorderLayout.NORTH);
|
||||
|
||||
@@ -81,11 +81,13 @@ public class Client extends JFrame {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent mouseEvent) {
|
||||
super.mouseClicked(mouseEvent);
|
||||
System.out.println(mouseEvent);
|
||||
System.out.println("down "+mouseEvent);
|
||||
int x = mouseEvent.getX();
|
||||
int y = mouseEvent.getY();
|
||||
try {
|
||||
writer.write("DOWN"+(x*1.0f/label.getWidth() )+ "#" + (y*1.0f/label.getHeight()));
|
||||
writer.write("DOWN" + (x * 1.0f / label.getWidth()) + "#" + (y * 1.0f / label.getHeight()));
|
||||
writer.newLine();
|
||||
writer.write("UP" + (x * 1.0f / label.getWidth()) + "#" + (y * 1.0f / label.getHeight()));
|
||||
writer.newLine();
|
||||
writer.flush();
|
||||
} catch (Exception e) {
|
||||
@@ -96,13 +98,14 @@ public class Client extends JFrame {
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent mouseEvent) {
|
||||
super.mouseReleased(mouseEvent);
|
||||
System.out.println("mouseReleased " );
|
||||
System.out.println("up mouseReleased");
|
||||
try {
|
||||
int x = mouseEvent.getX();
|
||||
int y = mouseEvent.getY();
|
||||
writer.write("UP"+(x*1.0f/label.getWidth() )+ "#" + (y*1.0f/label.getHeight()));
|
||||
writer.write("UP" + (x * 1.0f / label.getWidth()) + "#" + (y * 1.0f / label.getHeight()));
|
||||
writer.newLine();
|
||||
writer.flush();
|
||||
isMove = false;
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
@@ -112,11 +115,19 @@ public class Client extends JFrame {
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent mouseEvent) {
|
||||
super.mouseDragged(mouseEvent);
|
||||
System.out.println("mouseDragged "+mouseEvent.getX()+" "+mouseEvent.getY());
|
||||
try {
|
||||
int x = mouseEvent.getX();
|
||||
int y = mouseEvent.getY();
|
||||
writer.write("MOVE"+(x*1.0f/label.getWidth() )+ "#" + (y*1.0f/label.getHeight()));
|
||||
if (!isMove) {
|
||||
isMove = true;
|
||||
System.out.println("down mouseDragged " + mouseEvent.getX() + " " + mouseEvent.getY());
|
||||
|
||||
writer.write("DOWN" + (x * 1.0f / label.getWidth()) + "#" + (y * 1.0f / label.getHeight()));
|
||||
} else {
|
||||
System.out.println("move mouseDragged " + mouseEvent.getX() + " " + mouseEvent.getY());
|
||||
|
||||
writer.write("MOVE" + (x * 1.0f / label.getWidth()) + "#" + (y * 1.0f / label.getHeight()));
|
||||
}
|
||||
writer.newLine();
|
||||
writer.flush();
|
||||
} catch (Exception e) {
|
||||
@@ -126,19 +137,7 @@ public class Client extends JFrame {
|
||||
|
||||
|
||||
});
|
||||
// label.addMouseWheelListener(new MyMouseAdapter(){
|
||||
// @Override
|
||||
// public void mouseWheelMoved(MouseWheelEvent mouseWheelEvent) {
|
||||
// super.mouseWheelMoved(mouseWheelEvent);
|
||||
// System.out.println("mouseWheelMoved "+mouseWheelEvent);
|
||||
// }
|
||||
//
|
||||
// // @Override
|
||||
//// public void mouseDragged(MouseEvent mouseEvent) {
|
||||
//// super.mouseDragged(mouseEvent);
|
||||
//// System.out.println("mouseDragged");
|
||||
//// }
|
||||
// });
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -177,7 +176,7 @@ public class Client extends JFrame {
|
||||
label.setIcon(new ScaleIcon(new ImageIcon(image)));
|
||||
long s3 = System.currentTimeMillis();
|
||||
|
||||
// System.out.println("读取: " + (s2 - s1) + " 解码: " + (s3 - s2) + " " + length);
|
||||
// System.out.println("读取: " + (s2 - s1) + " 解码: " + (s3 - s2) + " " + length);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -1 +1 @@
|
||||
include ':app', ':lib'
|
||||
include ':app', ':lib', ':shareandcontrollib'
|
||||
|
||||
1
shareandcontrollib/.gitignore
vendored
Normal file
1
shareandcontrollib/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
31
shareandcontrollib/build.gradle
Normal file
31
shareandcontrollib/build.gradle
Normal file
@@ -0,0 +1,31 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
compile 'com.android.support:appcompat-v7:25.2.0'
|
||||
testCompile 'junit:junit:4.12'
|
||||
}
|
||||
17
shareandcontrollib/proguard-rules.pro
vendored
Normal file
17
shareandcontrollib/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/wanjian/Library/Android/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumentation test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.wanjian.puppet.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
11
shareandcontrollib/src/main/AndroidManifest.xml
Normal file
11
shareandcontrollib/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.wanjian.puppet">
|
||||
|
||||
<application android:allowBackup="true"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,18 @@
|
||||
package android.hardware.display;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public interface IDisplayManager {
|
||||
DisplayInfo getDisplayInfo(int i);
|
||||
|
||||
abstract class Stub {
|
||||
public static IDisplayManager asInterface(IBinder invoke) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package android.view;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public interface DisplayInfo {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package android.view;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public interface IRotationWatcher {
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package android.view;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public interface IWindowManager {
|
||||
void getInitialDisplaySize(int i, Point displaySize);
|
||||
|
||||
int getRotation();
|
||||
|
||||
void getRealDisplaySize(Point displaySize);
|
||||
|
||||
abstract class Stub {
|
||||
|
||||
public static IWindowManager asInterface(IBinder invoke) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
279
shareandcontrollib/src/main/java/com/wanjian/puppet/Main.java
Normal file
279
shareandcontrollib/src/main/java/com/wanjian/puppet/Main.java
Normal file
@@ -0,0 +1,279 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.net.LocalServerSocket;
|
||||
import android.net.LocalSocket;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v4.view.InputDeviceCompat;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.InputEvent;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public class Main {
|
||||
|
||||
private static InputManager im;
|
||||
private static Method injectInputEventMethod;
|
||||
private static long downTime;
|
||||
|
||||
private static IWindowManager wm;
|
||||
|
||||
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
|
||||
|
||||
System.out.println("start!");
|
||||
LocalServerSocket serverSocket = new LocalServerSocket("puppet-ver1");
|
||||
|
||||
init();
|
||||
|
||||
while (true) {
|
||||
System.out.println("listen.....");
|
||||
LocalSocket socket = serverSocket.accept();
|
||||
acceptConnect(socket);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void init() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
|
||||
System.out.println("init...");
|
||||
Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
|
||||
wm = IWindowManager.Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));
|
||||
|
||||
im = (InputManager) InputManager.class.getDeclaredMethod("getInstance", new Class[0]).invoke(null, new Object[0]);
|
||||
MotionEvent.class.getDeclaredMethod("obtain", new Class[0]).setAccessible(true);
|
||||
injectInputEventMethod = InputManager.class.getMethod("injectInputEvent", new Class[]{InputEvent.class, Integer.TYPE});
|
||||
|
||||
System.out.println("init finished...");
|
||||
}
|
||||
|
||||
private static void acceptConnect(LocalSocket socket) {
|
||||
System.out.println("accepted...");
|
||||
read(socket);
|
||||
write(socket);
|
||||
}
|
||||
|
||||
private static void write(final LocalSocket socket) {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
try {
|
||||
final int VERSION = 2;
|
||||
BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
|
||||
while (true) {
|
||||
Bitmap bitmap = screenshot();
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 60, byteArrayOutputStream);
|
||||
|
||||
outputStream.write(2);
|
||||
writeInt(outputStream, byteArrayOutputStream.size());
|
||||
outputStream.write(byteArrayOutputStream.toByteArray());
|
||||
outputStream.flush();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private static void read(final LocalSocket socket) {
|
||||
|
||||
new Thread() {
|
||||
private final String DOWN = "DOWN";
|
||||
private final String MOVE = "MOVE";
|
||||
private final String UP = "UP";
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
while (true) {
|
||||
String line;
|
||||
try {
|
||||
line = reader.readLine();
|
||||
if (line == null) {
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (line.startsWith(DOWN)) {
|
||||
hanlerDown(line.substring(DOWN.length()));
|
||||
// hanlerUp(line.substring(DOWN.length()));
|
||||
} else if (line.startsWith(MOVE)) {
|
||||
hanlerMove(line.substring(MOVE.length()));
|
||||
} else if (line.startsWith(UP)) {
|
||||
hanlerUp(line.substring(UP.length()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private static void hanlerUp(String line) {
|
||||
Point point = getXY(line);
|
||||
if (point != null) {
|
||||
try {
|
||||
touchUp(point.x, point.y);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void hanlerMove(String line) {
|
||||
Point point = getXY(line);
|
||||
if (point != null) {
|
||||
try {
|
||||
touchMove(point.x, point.y);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void hanlerDown(String line) {
|
||||
Point point = getXY(line);
|
||||
if (point != null) {
|
||||
try {
|
||||
touchDown(point.x, point.y);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Point getXY(String nums) {
|
||||
try {
|
||||
Point point = SurfaceControlVirtualDisplayFactory.getCurrentDisplaySize(false);
|
||||
String[] s = nums.split("#");
|
||||
float scaleX = Float.parseFloat(s[0]);
|
||||
float scaleY = Float.parseFloat(s[1]);
|
||||
point.x *= scaleX;
|
||||
point.y *= scaleY;
|
||||
System.out.println("point x=" + point.x + " y=" + point.y);
|
||||
return point;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static void writeInt(OutputStream outputStream, int v) throws IOException {
|
||||
outputStream.write(v >> 24);
|
||||
outputStream.write(v >> 16);
|
||||
outputStream.write(v >> 8);
|
||||
outputStream.write(v);
|
||||
}
|
||||
|
||||
public static Bitmap screenshot() throws Exception {
|
||||
|
||||
String surfaceClassName;
|
||||
Point size = SurfaceControlVirtualDisplayFactory.getCurrentDisplaySize(false);
|
||||
if (Build.VERSION.SDK_INT <= 17) {
|
||||
surfaceClassName = "android.view.Surface";
|
||||
} else {
|
||||
surfaceClassName = "android.view.SurfaceControl";
|
||||
}
|
||||
Bitmap b = (Bitmap) Class.forName(surfaceClassName).getDeclaredMethod("screenshot", new Class[]{Integer.TYPE, Integer.TYPE}).invoke(null, new Object[]{Integer.valueOf(size.x), Integer.valueOf(size.y)});
|
||||
int rotation = wm.getRotation();
|
||||
if (rotation == 0) {
|
||||
return b;
|
||||
}
|
||||
Matrix m = new Matrix();
|
||||
if (rotation == 1) {
|
||||
m.postRotate(-90.0f);
|
||||
} else if (rotation == 2) {
|
||||
m.postRotate(-180.0f);
|
||||
} else if (rotation == 3) {
|
||||
m.postRotate(-270.0f);
|
||||
}
|
||||
return Bitmap.createBitmap(b, 0, 0, size.x, size.y, m, false);
|
||||
}
|
||||
|
||||
|
||||
private static void back() throws InvocationTargetException, IllegalAccessException {
|
||||
sendKeyEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_KEYBOARD, 4, false);
|
||||
}
|
||||
|
||||
|
||||
private static void touchUp(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
|
||||
System.out.println("up " + clientX + " " + clientY);
|
||||
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 1, downTime, SystemClock.uptimeMillis(), clientX, clientY, 1.0f);
|
||||
}
|
||||
|
||||
private static void touchMove(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
|
||||
System.out.println("move " + clientX + " " + clientY);
|
||||
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 2, downTime, SystemClock.uptimeMillis(), clientX, clientY, 1.0f);
|
||||
}
|
||||
|
||||
private static void touchDown(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
|
||||
System.out.println("down " + clientX + " " + clientY);
|
||||
downTime = SystemClock.uptimeMillis();
|
||||
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 0, downTime, downTime, clientX, clientY, 1.0f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void pressHome() throws InvocationTargetException, IllegalAccessException {
|
||||
sendKeyEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_KEYBOARD, 3, false);
|
||||
}
|
||||
|
||||
|
||||
private static void injectMotionEvent(InputManager im, Method injectInputEventMethod, int inputSource, int action, long downTime, long eventTime, float x, float y, float pressure) throws InvocationTargetException, IllegalAccessException {
|
||||
MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, pressure, 1.0f, 0, 1.0f, 1.0f, 0, 0);
|
||||
event.setSource(inputSource);
|
||||
injectInputEventMethod.invoke(im, new Object[]{event, Integer.valueOf(0)});
|
||||
}
|
||||
|
||||
private static void injectKeyEvent(InputManager im, Method injectInputEventMethod, KeyEvent event) throws InvocationTargetException, IllegalAccessException {
|
||||
injectInputEventMethod.invoke(im, new Object[]{event, Integer.valueOf(0)});
|
||||
}
|
||||
|
||||
|
||||
private static void sendKeyEvent(InputManager im, Method injectInputEventMethod, int inputSource, int keyCode, boolean shift) throws InvocationTargetException, IllegalAccessException {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
int meta = shift ? 1 : 0;
|
||||
injectKeyEvent(im, injectInputEventMethod, new KeyEvent(now, now, 0, keyCode, 0, meta, -1, 0, 0, inputSource));
|
||||
injectKeyEvent(im, injectInputEventMethod, new KeyEvent(now, now, 1, keyCode, 0, meta, -1, 0, 0, inputSource));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.display.IDisplayManager;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.IRotationWatcher;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.IWindowManager.Stub;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class SurfaceControlVirtualDisplayFactory implements VirtualDisplayFactory {
|
||||
private static final String LOGTAG = "SCVDF";
|
||||
Rect displayRect;
|
||||
Point displaySize = getCurrentDisplaySize();
|
||||
|
||||
public static Point getCurrentDisplaySize() {
|
||||
return getCurrentDisplaySize(true);
|
||||
}
|
||||
|
||||
public static Point getCurrentDisplaySize(boolean rotate) {
|
||||
try {
|
||||
Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
|
||||
Point displaySize = new Point();
|
||||
IWindowManager wm;
|
||||
int rotation;
|
||||
if (VERSION.SDK_INT >= 18) {
|
||||
wm = Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));
|
||||
wm.getInitialDisplaySize(0, displaySize);
|
||||
rotation = wm.getRotation();
|
||||
} else if (VERSION.SDK_INT == 17) {
|
||||
DisplayInfo di = IDisplayManager.Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"display"})).getDisplayInfo(0);
|
||||
displaySize.x = ((Integer) DisplayInfo.class.getDeclaredField("logicalWidth").get(di)).intValue();
|
||||
displaySize.y = ((Integer) DisplayInfo.class.getDeclaredField("logicalHeight").get(di)).intValue();
|
||||
rotation = ((Integer) DisplayInfo.class.getDeclaredField("rotation").get(di)).intValue();
|
||||
} else {
|
||||
wm = Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));
|
||||
wm.getRealDisplaySize(displaySize);
|
||||
rotation = wm.getRotation();
|
||||
}
|
||||
if ((rotate && rotation == 1) || rotation == 3) {
|
||||
int swap = displaySize.x;
|
||||
displaySize.x = displaySize.y;
|
||||
displaySize.y = swap;
|
||||
}
|
||||
return displaySize;
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public VirtualDisplay createVirtualDisplay(String name, int width, int height, int dpi, int flags, Surface surface, Handler handler) {
|
||||
try {
|
||||
Class surfaceControlClass = Class.forName("android.view.SurfaceControl");
|
||||
Class cls = surfaceControlClass;
|
||||
final IBinder token = (IBinder) cls.getDeclaredMethod("createDisplay", new Class[]{String.class, Boolean.TYPE}).invoke(null, new Object[]{name, Boolean.valueOf(false)});
|
||||
cls = surfaceControlClass;
|
||||
Method setDisplaySurfaceMethod = cls.getDeclaredMethod("setDisplaySurface", new Class[]{IBinder.class, Surface.class});
|
||||
cls = surfaceControlClass;
|
||||
final Method setDisplayProjectionMethod = cls.getDeclaredMethod("setDisplayProjection", new Class[]{IBinder.class, Integer.TYPE, Rect.class, Rect.class});
|
||||
cls = surfaceControlClass;
|
||||
Method setDisplayLayerStackMethod = cls.getDeclaredMethod("setDisplayLayerStack", new Class[]{IBinder.class, Integer.TYPE});
|
||||
final Method openTransactionMethod = surfaceControlClass.getDeclaredMethod("openTransaction", new Class[0]);
|
||||
final Method closeTransactionMethod = surfaceControlClass.getDeclaredMethod("closeTransaction", new Class[0]);
|
||||
final Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
|
||||
this.displayRect = new Rect(0, 0, width, height);
|
||||
Rect layerStackRect = new Rect(0, 0, this.displaySize.x, this.displaySize.y);
|
||||
openTransactionMethod.invoke(null, new Object[0]);
|
||||
setDisplaySurfaceMethod.invoke(null, new Object[]{token, surface});
|
||||
setDisplayProjectionMethod.invoke(null, new Object[]{token, Integer.valueOf(0), layerStackRect, this.displayRect});
|
||||
setDisplayLayerStackMethod.invoke(null, new Object[]{token, Integer.valueOf(0)});
|
||||
closeTransactionMethod.invoke(null, new Object[0]);
|
||||
cls = surfaceControlClass;
|
||||
final Method destroyDisplayMethod = cls.getDeclaredMethod("destroyDisplay", new Class[]{IBinder.class});
|
||||
return new VirtualDisplay() {
|
||||
IRotationWatcher watcher;
|
||||
IWindowManager wm = Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));
|
||||
|
||||
public void release() {
|
||||
Log.i(SurfaceControlVirtualDisplayFactory.LOGTAG, "VirtualDisplay released");
|
||||
this.wm = null;
|
||||
this.watcher = null;
|
||||
try {
|
||||
destroyDisplayMethod.invoke(null, new Object[]{token});
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Point getDisplaySize() {
|
||||
return new Point(this.displaySize);
|
||||
}
|
||||
|
||||
public Rect getDisplayRect() {
|
||||
return this.displayRect;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
Log.i(LOGTAG, "factory released");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
public interface VirtualDisplay {
|
||||
void release();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.wanjian.puppet.VirtualDisplay;
|
||||
|
||||
public interface VirtualDisplayFactory {
|
||||
VirtualDisplay createVirtualDisplay(String str, int i, int i2, int i3, int i4, Surface surface, Handler handler);
|
||||
|
||||
void release();
|
||||
}
|
||||
3
shareandcontrollib/src/main/res/values/strings.xml
Normal file
3
shareandcontrollib/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">shareAndControlLib</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user