Only support ES5
Add the following <script> in the <head> section of index.html
start() and stop() should defined in index.js
<script>
function onEvent(eventType) {
if (eventType === 'OnPlayClick') {
JavaScriptInterface.runScript(`start();`);
} else if (eventType === 'OnPauseClick') {
JavaScriptInterface.runScript('stop();');
}
}
function onLog(message) {
console.log(message);
}
</script>| event name |
|---|
| OnMenuClick |
| OnPlayClick |
| OnPauseClick |
| OnLogClick |
| OnSettingClick |
| OnCloseClick |
runScript(script)scriptString
runScriptCallback(script, callback)scriptStringcallbackString
clickIconButton()Click the app icon button on floating widget.
clickPlayButton()Click the play button on floating widget.
clickPauseButton()Click the pause button on floating widget.
clickLogButton()Click the log button on floating widget.
clickSettingButton()Click the setting button on floating widget.
clickCloseButton()Click the close button on floating widget.
setXY(x, y)xIntegeryInteger
Set the position of the floating widget.
getX()Returns Integer - The x position of the floating widget.
getY()Returns Integer - The y position of the floating widget.
showMenu()Show the menu on floating widget.
hideMenu()Hide the menu on floating widget.
showPlayButton()Show the play button on floating widget.
showPauseButton()Show the pause button on floating widget.
Returns Object - {width: Integer, height: Integer}
var sizeObj = getScreenSize();
console.log(sizeObj.width, sizeObj.height);
// 1080 1920Returns Integer - The image pointer
var img = getScreenshot();
console.log(img);
// 122344533 <- image pointer
releaseImage(img); // Don't forgot release a pointerGet screenshot, crop and resize. For speeding up screenshot.
cropXIntegercropYIntegercropWidthIntegercropHeightIntegerresizeWidthIntegerresizeHeightIntegerqualityInteger
Returns Integer - The image pointer
var image = getScreenshotModify(200, 200, 100, 100, 50, 50, 80);
console.log(image); // image width = 50, height = 50
// 12333122
releaseImage(image);Call exec command in android system. Its permission is same as adb shell
commandString
Returns String - The result of the execution
var result = execute("ls -al /sdcard");
console.log(result);
// drwxr-xr-x 2 root root 64B 12 14 23:44 RobotmonSimulate a tap event after during milliseconds have passed.
xIntegeryIntegerduringInteger time to wait before tap in milliseconds
tap(200, 200, 10);
// Will inject a tap down and a tap up event after 10ms to systemxIntegeryIntegerduringInteger time to wait before tapDown in milliseconds
tapDown(200, 200, 40);
// Will inject a tapDown event after 10ms to systemxIntegeryIntegerduringInteger time to wait before tapUp in milliseconds
tapUp(200, 200, 40);
// Will inject a tapUo event after 10ms to systemmoveTo should be between tapDown and tapUp
xIntegeryIntegerduringInteger
tapDown(500, 300, 40);
moveTo(500, 600, 40);
tapUp(500, 600, 40);
// Will inject a swipe down eventSimulate a swipe event, using tapDown, moveTo and tapUp event. This function may not work in some game, you should implement yourself.
x1Integery1Integerx2Integery2IntegerduringInteger
swipe(500, 300, 40); // same as above example
// Will inject a swipe down eventSend a key code event to system
Like adb shell input keyevent command
Android Keycode List
labelStringduringInteger
keycode('HOME', 40); // same as keycode('KEYCODE_HOME', 40);
// Will send a HOME event to systemOnly allow English words
wordsStringduringInteger
typing('Hello!', 100);
// Will type 'H' 'e' 'l' 'l' 'o' '!' 6 wordsDuplicate an image to another.
sourceImgInteger
Returns Integer - The image pointer
var oriImage = getScreenshot();
for (var i = 0; i < 10; i++) {
var cloneImage = clone(oriImage);
// modify clone Image here
smooth(cloneImage, 1, 5); // blur
release(cloneImage);
}
release(oriImage);Same as OpenCV smooth() function.
sourceImgIntegersmoothTypeIntegersizeInteger
| smoothType | description |
|---|---|
| 0 | CV_BLUR_NO_SCALE |
| 1 | CV_BLUR |
| 2 | CV_GAUSSIAN |
| 3 | CV_MEDIAN |
| 4 | CV_BILATERAL |
var img = getScreenshot();
smooth(img, 2, 5); // Gaussian blur
saveImage(img, getStoragePath + '/smooth.png');
releaseImage(img);Same as OpenCV cvtColor(). Not support different channels. If you want to convert to gray, please use bgrToGray.
Note that getScreenshot and getScreenshotModify is BGR order;
sourceImgIntegercodeInteger
| code | description |
|---|---|
| 40 | CV_BGR2HSV |
| 52 | CV_BGR2HLS |
See more: OpenCV Types
var img = getScreenshot();
// Convert BGR to HSV color
convertColor(img, 40);
releaseImage(img);Convert form bgr (3 channels) to gray (1 channel).
sourceImgInteger
Returns Integer - The gray image pointer
var img = getScreenshot();
var gray = bgrToGray(img); // gray image
releaseImage(img);
releaseImage(gray);Same as OpenCV adbdiff().
sourceImgIntegertargetImgInteger
Returns Integer - The image pointer of the difference
var img1 = getScreenshot();
sleep(100);
var img2 = getScreenshot();
var diff = absDiff(img1, img2); // in gray order
releaseImage(img1);
releaseImage(img2);
releaseImage(diff);Same as OpenCV threshold().
sourceImgIntegerthrFloatmaxThrFloatcodeInteger
| code | description |
|---|---|
| 0 | CV_THRES_BINARY |
See more: OpenCV Types
keycode('MENU');
sleep(1000);
var img1 = getScreenshot();
keycode('HOME');
sleep(1000);
var img2 = getScreenshot();
var diff = absDiff(img1, img2); // in gray order
threshold(diff, 100, 255); // set to 0 if <= 100, set to 255 if > 100
var value = getImageColor(diff, 500, 200); // value => {r":255,"g":0,"b":0","a":0}
console.log(value['r']); // current diff value is show on 'r'
// 255
releaseImage(img1);
releaseImage(img2);
releaseImage(diff);Same as OpenCV eroid.
width, height, x, y is getStructuringElement() parameters.
sourceImgIntegerwidthIntegerheightIntegerxIntegeryInteger
var img = getScreenshot();
threshold(img, 100, 255);
eroid(img, 3, 3, 1, 1);
saveImage(img, getStoragePath() + '/test_eroid.png');
releaseImage(img);Same as OpenCV dilate.
width, height, x, y is getStructuringElement() parameters.
sourceImgIntegerwidthIntegerheightIntegerxIntegeryInteger
var img = getScreenshot();
threshold(img, 100, 255);
dilate(img, 3, 3, 1, 1);
saveImage(img, getStoragePath() + '/test_dilate.png');
releaseImage(img);Same as OpenCV inRange + clone + mask. Filter with range color and clone to new image.
sourceImgIntegerminBIntegerminGIntegerminRIntegerminAIntegermaxBIntegermaxGIntegermaxRIntegermaxAInteger
Returns Integer - The filtered image pointer
var img = getScreenshot();
var filteredImg = inRange(img, 0, 255, 255, 255, 255, 255, 255, 255); // only keep blue color pixel
saveImage(filteredImg, getStoragePath() + '/test_filterd.png');
releaseImage(img);
releaseImage(filteredImg);Same as OpenCV inRange + clone + not + mask. Filter without range color and clone to new image.
sourceImgIntegerminBIntegerminGIntegerminRIntegerminAIntegermaxBIntegermaxGIntegermaxRIntegermaxAInteger
Returns Integer - The filtered image pointer
var img = getScreenshot();
var filteredImg = outRange(img, 0, 255, 255, 255, 255, 255, 255, 255); // keep all but blue color
saveImage(filteredImg, getStoragePath() + '/test_filterd.png');
releaseImage(img);
releaseImage(filteredImg);Same as OpenCV copyTo. Clone image with mask (only support 1 channel)
sourceImgIntegermaskInteger
Returns Integer - new image pointer with mask
var img1 = getScreenshot();
sleep(100);
var img2 = getScreenshot();
var diff = absDiff(img1, img2);
sleep(100);
var img3 = cloneWithMask(img1, diff);
releaseImage(img1);
releaseImage(img2);
releaseImage(img3);
releaseImage(diff);Same as OpenCV houghCircles. For finding circles.
sourceImgIntegermethodInteger (3 = CV_HOUGH_GRADIENT)dpFloat (1) (ratio between input image and input params.)minDistFloat (min distance between circles)p1Float (canny parameter)p2Float (canny parameter)minRInteger (min radius)maxRInteger (max radius)
Returns Object - Array of circles
var img = getScreenshot();
var points = houghCircles(img, 3, 1, 8, 4, 8, 6, 14);
console.log(points); // {"0": {"x": 102, "y": "233", "r": 9}}
releaseImage(img);Same as OpenCV canny
sourceImgIntegert1Floatt2FloatapertureSizeInteger
Returns Integer - The canny image pointer
var img = getScreenshot();
threshold(img, 30, 255);
eroid(img, 5, 5, 1, 1);
var cannyImg = canny(img, 50, 150, 3);
saveImage(cannyImg, getStoragePath() + '/test_canny.png');
releaseImage(img);
releaseImage(cannyImg);Same as OpenCV findContours.
cannyImgPtrInteger (Canny image as input)minAreaFloatmaxAreaFloat
Returns Object - {"0": {x: Integer, y: Integer}
var img = getScreenshot();
threshold(img, 30, 255);
eroid(img, 5, 5, 1, 1);
var cannyImg = canny(img, 50, 150, 3);
var results = findContours(cannyImg, 1000, 10000); // area > 100
console.log(JSON.stringify(results));
// {"0":{"x":537,"y":1850},"1":{"x":133,"y":601}}
releaseImage(img);
releaseImage(cannyImg);Draw circle in an image.
sourceImgIntegerxIntegeryIntegerradiusIntegerrIntegergIntegerbIntegeraInteger
var img = getScreenshot();
drawCircle(img, 100, 100, 10, 0, 0, 255, 0); // draw a blue circle
saveImage(img, getStoragePath() + '/test_drawCircle.png');
releaseImage(img);sourceImgIntegertargetImgInteger
Returns Float - The identity score
keycode('MENU');
sleep(1000);
var img1 = getScreenshot();
keycode('HOME');
sleep(1000);
var img2 = getScreenshot();
var score = getIdentityScore(img1, img2);
console.log(score); // 0.6004924774169922
releaseImage(img1);
releaseImage(img2);Crop image.
xIntegeryIntegerwidthIntegerheightInteger
Returns Integer - The image pointer
var img = getScreenshot();
var cropImg = cropImage(img, 350, 550, 150, 150);
saveImage(cropImg, getStoragePath() + '/test_crop.png');
releaseImage(img);
releaseImage(cropImg);Using OpenCV Template Match to find image.
sourceImgIntegertargetImgInteger
Returns Object - {x: Integer, y: Integer, score: Float}
var img = getScreenshot();
var cropImg = cropImage(img, 350, 550, 150, 150);
var result = findImage(img, cropImg);
console.log(JSON.stringify(result)); // {"score":0.9999997615814209,"x":350,"y":550}
releaseImage(img);
releaseImage(cropImg);Same as findImage(), but find multiple times.
sourceImgIntegertargetImgIntegerscoreLimitIntegerresultCountLimitIntegerwithoutOverlapBoolean
Returns String - {"0": {"x": Integer, "y": Integer, "score": Float}, "1": {"x": Integer, "y": Integer, "score": Float}}, Key is String!
var img = getScreenshot();
var cropImg = cropImage(img, 350, 550, 150, 150);
var result = findImages(img, cropImg, 0.95, 3, true);
console.log(JSON.stringify(result)); // {"0":{"score":0.9999997615814209,"x":350,"y":550}}
releaseImage(img);
releaseImage(cropImg);Resize image.
widthIntegerheightInteger
Returns Integer - The image pointer
var img = getScreenshot();
var resizeImg = resizeImage(img, 108, 192);
saveImage(resizeImg, getStoragePath() + '/test_resize.png');
releaseImage(img);
releaseImage(resizeImg);Very Important! You should call this function with all image pointers.
imagePointerInteger
var img = getScreenshot(); // keep in memory
releaseImage(img); // release from memoryGet color of point from an image.
sourceImgIntegerxIntegeryInteger
Returns Object - {r: Integer, g: Integer, b: Integer, a: Integer}
var img = getScreenshot();
var color = getImageColor(img, 100, 100);
console.log(JSON.stringify(color)); // {"a":0,"b":21,"g":36,"r":198}
releaseImage(img);imgPtrInteger
Returns Object - {width: Integer, height: Integer}
var img = getScreenshot();
var size = getImageSize(img);
console.log(JSON.stringify(size)); // {"height":1920,"width":1080}
releaseImage(img);Save image to disk.
imgPtrIntegerpathString
var img = getScreenshot();
saveImage(img, getStoragePath + '/test_save.png');
releaseImage(img);Open image from disk.
pathString
Returns Integer - The image pointer
var img = openImage(getStoragePath + '/test_save.png');
releaseImage(img);Like sleep function in C language, pause current process.
millisecondsInteger
console.log('Hello');
sleep(1000);
console.log('Andy');Get Robotmon folder. Like /sdcard/Robotmon.
Returns String - The storage path
console.log(getStoragePath());Get image from an url.
urlString
Returns Integer - The image pointer
Get image from a base64 string.
base64String
Returns Integer - The image pointer
Get base64 string from an image.
imgPtrInteger
Returns String - base64
Read a file as string.
pathString
Returns String - The text of the file
Write a string to a file.
pathStringtextString
Encrypted a string
scriptString
Returns String - The encrypted script
Run an encrypted javascript string.
scriptString - The script is encrypted byencrypt
Run a javascript string.
scriptString
Do a http request.
methodStringurlStringbodyStringheadersObject
Returns String - The result
httpClient('GET', 'http://httpbin.org/get', '', {});
httpClient('POST', 'http://httpbin.org/post', 'body data', {});
httpClient('POST', 'http://httpbin.org/post', 'foo=bar&bar=foo', {'Content-Type': 'application/x-www-form-urlencoded'});Import an JS library.
libraryString
importJS('RBM-0.0.2') // import shared library in libs
importJS('js/customerJS') // import local libraryReturns Integer - The height of the virtual button
The RBM library is an API wrapper of the Robotmon JavaScript APIs.
| property | description |
|---|---|
| appName | The name of the script. |
| oriScreenWidth | The width of developer's phone. |
| oriScreenHeight | The height of developer's phone. |
| oriVirtualButtonHeight | The virtual button height of developer's phone(getVirtualButtonHeight()). If no virtual button in app, just set to 0. |
| oriResizeFactor | The resize ratio of the screenshot in developer's environment. For screencrop(). Range from 0 to 1. |
| eventDelay | The delay milliseconds of the event. |
| imageThreshold | The threshold of image recognition. Range from 0 to 1. |
| imageQuality | The compression level of the image. Range from 0 to 100. |
| resizeFactor | The resize ratio of the screenshot in user's environment. Same as oriResizeFactor is better. Range from 0 to 1. |
// Import RBM library
importJS('RBM-0.0.2');
// Initial RBM config
var config = {
appName: 'com.your.script',
oriScreenWidth: 1080,
oriScreenHeight: 1920,
oriVirtualButtonHeight: 0,
oriResizeFactor: 0.6,
eventDelay: 200,
imageThreshold: 0.85,
imageQuality: 80,
resizeFactor: 0.6,
};
// Create RBM instance
var rbm = new RBM(config);
// Important! Calculate the screen size, call it after start pressed!
rbm.init();
// Then using the following APIs of the RBM libraryrbm.log(args)argsany type - if argument is object, it will convert object to JSON string
For general output of logging information.
rbm.currentApp()Returns Object - The current app in foreground. {packageName: String, activityName: String}
rbm.startApp(packageName, activityName)packageNameStringactivityNameString
Launch an app by packageName and activityName.
rbm.stopApp(packageName)packageNameString
Close an app by packageName.
rbm.click(position)positionObject -{x: Integer, y: Integer}
rbm.tapDown(position)positionObject -{x: Integer, y: Integer}
rbm.tapUp(position)positionObject -{x: Integer, y: Integer}
rbm.moveTo(position)positionObject -{x: Integer, y: Integer}
rbm.swipe(from, to, steps)fromObject -{x: Integer, y: Integer}toObject -{x: Integer, y: Integer}stepsInteger - Interpolation points betweenfromandto
rbm.keycode(label)labelString
rbm.typing(words)wordsString
rbm.sleep()Sleep with eventDelay.
rbm.getImagePath()
// /sdcard/Robotmon/scripts/com.your.app/imagesReturns String - The path of the image folder. All about images used in this library will load and save within this folder.
rbm.screenshot(filename)filenameString
Save the screenshot in rbm.getImagePath().
rbm.oriScreencrop(filename, fromX, fromY, toX, toY)
// Examples:
rbm.oriScreencrop('startButton.png', 100, 200, 200, 300)filenameStringfromXIntegerfromYIntegertoXIntegertoYInteger
Crop the original screenshot and save it with filename. This function will resize the image with oriResizeFactor and compress with imageQuality.
rbm.screencrop(filename, fromX, fromY, toX, toY)
// Examples:
rbm.screencrop('startButton.png', 100, 200, 200, 300)filenameStringfromXIntegerfromYIntegertoXIntegertoYInteger
Crop the screenshot and save it with filename. This function will resize the image with resizeFactor and compress with imageQuality.
rbm.findImage(filename, threshold)
// Examples:
rbm.findImage('startButton.png', 0.9)filenameStringthresholdFloat
Returns Object - Find the image with filename in screen. {x: Integer, y: Integer, score: Float}
rbm.findImages(filename, threshold, countLimit, allowOverlap, deep)
// Examples:
rbm.findImages('startButton.png', 0.9, 3, false, false)filenameStringthresholdFloatcountLimitIntegerallowOverlapBooleandeepBoolean
Returns Object - Find the image with filename in screen. {x: Integer, y: Integer, score: Float}
rbm.imageExists(filename, threshold)filenameStringthresholdFloat
Returns Boolean - Whether the image exists in screen.
rbm.imageClick(filename, threshold)filenameStringthresholdFloat
Click the image if the image exists in screen.
rbm.imageWaitClick(filename, timeout, threshold)filenameStringtimeoutIntegerthresholdFloat
Click the image if the image exists in screen until timeout (milliseconds).
rbm.imageWaitShow(filename, timeout, threshold)filenameStringtimeoutIntegerthresholdFloat
Block until the image is found or timeout
rbm.imageWaitGone(filename, timeout, threshold)filenameStringtimeoutIntegerthresholdFloat
Block until the image is gone or timeout
rbm.keepScreenshot()Keep the screenshot in memory. To avoid too many times screencap.
rbm.screencrop(fromX, fromY, toX, toY)fromXIntegerfromYIntegertoXIntegertoYInteger
Keep the partial screenshot in memory. To avoid too many times screencap.
rbm.releaseScreenshot()Release the screenshot in memory.
// Screencap three times
rbm.imageClick('apple.png', 0.9); // screencap, and release
rbm.imageClick('banana.png', 0.9); // screencap, and release
rbm.imageClick('cat.png', 0.9); // screencap, and release
// Screencap only one time (used when the screen has not changed)
rbm.keepScreenshot(); // screencap
rbm.imageClick('apple.png', 0.9); // no screencap, no release
rbm.imageClick('banana.png', 0.9); // no screencap, no release
rbm.imageClick('cat.png', 0.9); // no screencap, no release
rbm.releaseScreenshot(); // releasemessage Empty {}
message Response {
string message = 1;
}
message RequestRunScript {
string script = 1;
}
message RequestScreenshot {
int32 cropX = 1;
int32 cropY = 2;
int32 cropWidth = 3;
int32 cropHeight = 4;
int32 resizeWidth = 5;
int32 resizeHeight = 6;
int32 quality = 7;
}
message RequestTap {
int32 x = 1;
int32 y = 2;
int32 during = 3;
}
message ResponseScreenshot {
bytes image = 1;
}
message ResponseScreenSize {
int32 width = 1;
int32 height = 2;
}service GrpcService {
rpc RunScript(RequestRunScript) returns (Response) {}
rpc Logs(Empty) returns (stream Response) {}
rpc GetScreenshot(RequestScreenshot) returns (ResponseScreenshot) {}
rpc GetScreenSize(Empty) returns (ResponseScreenSize) {}
rpc Tap(RequestTap) returns (Response) {}
rpc TapDown(RequestTap) returns (Response) {}
rpc TapUp(RequestTap) returns (Response) {}
rpc MoveTo(RequestTap) returns (Response) {}
}- use 'robotmon-desktop/light-manager' 'StartService''
- use 'robotmon-desktop/light-manager' 'EnableRemotePhone'
- reconnect USB ethernet tethering if required
- On mobile, launch the 'Robotmon' click menu/IP to get IP of mobile
- On mobile, launch the 'Robotmon' click any script
- build 'robotmon-desktop/app' on linux
- run 'robotmon-desktop/app' click 'Robotmon Devices' 新增 IP
- click '同步螢幕' if required
- run 'adb logcat | grep Robotmon:' to show related message