Compare commits

...

29 Commits

Author SHA1 Message Date
Andrew Grieve
d29eb84010 Tagging 2.4.0rc2 2013-01-30 09:51:40 -05:00
Joe Bowser
381ce535bf Merge branch 'puritytool' 2013-01-29 15:20:21 -08:00
Andrew Grieve
2e20bb0639 [CB-2293] Fix typo bufferSize->bytesRead.
Also adds a log statement to print out amount uploaded when an
IOException is thrown.
2013-01-29 13:47:15 -05:00
Joe Bowser
56cd24797e Fix for CB-2284. 401s are appearing when we hit them 2013-01-25 16:39:02 -08:00
Joe Bowser
431ca99c23 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/cordova-android 2013-01-25 14:41:26 -08:00
Joe Bowser
6ced2ff293 CB-2292: Added a check for width and height. You can't scale nothing because you can't divide by zero. 2013-01-25 14:41:14 -08:00
Joe Bowser
31055bb303 Update to purity, adding better touch support 2013-01-25 14:39:44 -08:00
Fil Maj
24a53e39dd hey new line 2013-01-23 18:31:30 -08:00
Fil Maj
2ab113b695 Removing notice about incubation in the readme. 2013-01-23 12:21:49 -08:00
Fil Maj
9a0481a750 tweaking readme 2013-01-23 12:17:42 -08:00
Fil Maj
09035eb4c4 Setting template AndroidManifest values for version to 1.0 and code to 1. 2013-01-23 12:13:07 -08:00
Joe Bowser
1adf268e71 Updates to tests, including the use of Purity 2013-01-22 15:18:21 -08:00
Joe Bowser
23f57ad5a7 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/cordova-android into puritytool 2013-01-21 14:59:04 -08:00
Joe Bowser
d9b15cf69e Updating with fixed JS from CB-2279 2013-01-21 13:47:26 -08:00
Joe Bowser
dbfe12a993 Partial fix for CB-2269, we probably shoudln't call Config.init twice 2013-01-18 16:41:10 -08:00
Joe Bowser
2b32dfd99d Partial Fix for CB-2269
* Moved Config.init call into DroidGap for the most common use-case
  * The CordovaWebView docuemntation still has to be updated
  * The template has to be changed, since we don't want to have two different types of config
2013-01-18 16:37:55 -08:00
Joe Bowser
679de40780 2.4.0rc1 updating 2013-01-18 15:33:38 -08:00
Joe Bowser
66f15fdd37 Adding purity to the test suite. Purity is a test class that may be renamed later 2013-01-18 15:00:02 -08:00
Joe Bowser
038f0e45b1 Upgrading Test Project properties to 4.2 2013-01-18 11:44:09 -08:00
Joe Bowser
033bfcc804 This should be Android 4.2, not Google APIs 2013-01-18 11:36:12 -08:00
Braden Shepherdson
fa87c08a29 Merge branch 'master' into arraybuffers 2013-01-18 12:33:25 -05:00
Braden Shepherdson
dfb799739a Change binaryEcho to echoArrayBuffer. 2013-01-18 12:32:52 -05:00
Joe Bowser
1193f7ed22 Fixed Android 4.2 filepicker, time for master 2013-01-17 17:00:50 -08:00
Braden Shepherdson
7530c21a9f Full binary data support.
- Removed BinaryEcho; made Echo support a new binaryEcho action.
- Added CordovaArgs wrapper for JSONArray, and a new overload for
  execute that accepts a CordovaArgs. There is now a default
  implementation for the JSONArray version of execute that builds a
  CordovaArgs and calls that version of execute. The default
  implementation for the CordovaArgs execute is to return false.
- Added byte[] version of success() in CallbackContext.
2013-01-17 15:58:38 -05:00
Braden Shepherdson
547b683e61 Remove debugging. 2013-01-15 13:24:59 -05:00
Braden Shepherdson
ff1d943a69 Add CordovaArguments helper to decode ArrayBuffers 2013-01-15 13:21:09 -05:00
Braden Shepherdson
15a5c89e86 Removed debugging output. 2013-01-15 11:52:06 -05:00
Braden Shepherdson
03b974ee3f Working Base64 encoding. 2013-01-15 11:48:09 -05:00
Braden Shepherdson
f145605c63 Mostly working arraybuffer changes, needs Base64. 2013-01-15 11:16:32 -05:00
26 changed files with 1501 additions and 908 deletions

View File

@@ -1,16 +1,12 @@
Cordova Android
===
Cordova Android is an Android application library that allows for Cordova based projects to be built for the Android Platform. Cordova based applications are, at the core, an application written with web technology: HTML, CSS and JavaScript.
Cordova Android is an Android application library that allows for Cordova-based
projects to be built for the Android Platform. Cordova based applications are,
at the core, applications written with web technology: HTML, CSS and JavaScript.
Apache Cordova is a project at The Apache Software Foundation (ASF).
Apache Cordova is an effort undergoing incubation at The Apache
Software Foundation (ASF), sponsored by the Apache Incubator project.
Incubation is required of all newly accepted projects until a further
review indicates that the infrastructure, communications, and decision
making process have stabilized in a manner consistent with other
successful ASF projects. While incubation status is not necessarily
a reflection of the completeness or stability of the code, it does
indicate that the project has yet to be fully endorsed by the ASF.
Requires
---

View File

@@ -1 +1 @@
2.3.0
2.4.0rc2

View File

@@ -28,7 +28,6 @@ public class __ACTIVITY__ extends DroidGap
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Config.init(this);
// Set by <content src="index.html" /> in config.xml
super.loadUrl(Config.getStartUrl());
//super.loadUrl("file:///android_asset/www/index.html")

View File

@@ -18,7 +18,7 @@
under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="__PACKAGE__" android:versionName="1.1" android:versionCode="5" android:hardwareAccelerated="true">
package="__PACKAGE__" android:versionName="1.0" android:versionCode="1" android:hardwareAccelerated="true">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"

View File

@@ -33,7 +33,7 @@
<p class="event received">Device is Ready</p>
</div>
</div>
<script type="text/javascript" src="cordova-2.3.0.js"></script>
<script type="text/javascript" src="cordova-2.4.0rc2.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();

View File

@@ -18,7 +18,7 @@
under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="org.apache.cordova" android:versionName="1.1" android:versionCode="5">
package="org.apache.cordova" android:versionName="1.0" android:versionCode="1">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@
<html>
<head>
<title></title>
<script src="cordova-2.3.0.js"></script>
<script src="cordova-2.4.0rc2.js"></script>
</head>
<body>

View File

@@ -571,7 +571,13 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
//CB-2292: WTF? Why is the width null?
if(options.outWidth == 0 || options.outHeight == 0)
{
return null;
}
// determine the correct aspect ratio
int[] widthHeight = calculateAspectRatio(options.outWidth, options.outHeight);

View File

@@ -0,0 +1,112 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
import org.json.JSONArray;
import org.json.JSONException;
import android.util.Base64;
public class CordovaArgs {
private JSONArray baseArgs;
public CordovaArgs(JSONArray args) {
this.baseArgs = args;
}
// Pass through the basics to the base args.
public Object get(int index) throws JSONException {
return baseArgs.get(index);
}
public boolean getBoolean(int index) throws JSONException {
return baseArgs.getBoolean(index);
}
public double getDouble(int index) throws JSONException {
return baseArgs.getDouble(index);
}
public int getInt(int index) throws JSONException {
return baseArgs.getInt(index);
}
public JSONArray getJSONArray(int index) throws JSONException {
return baseArgs.getJSONArray(index);
}
public Object getJSONObject(int index) throws JSONException {
return baseArgs.getJSONObject(index);
}
public long getLong(int index) throws JSONException {
return baseArgs.getLong(index);
}
public String getString(int index) throws JSONException {
return baseArgs.getString(index);
}
public Object opt(int index) {
return baseArgs.opt(index);
}
public boolean optBoolean(int index) {
return baseArgs.optBoolean(index);
}
public double optDouble(int index) {
return baseArgs.optDouble(index);
}
public int optInt(int index) {
return baseArgs.optInt(index);
}
public JSONArray optJSONArray(int index) {
return baseArgs.optJSONArray(index);
}
public Object optJSONObject(int index) {
return baseArgs.optJSONObject(index);
}
public long optLong(int index) {
return baseArgs.optLong(index);
}
public String optString(int index) {
return baseArgs.optString(index);
}
public boolean isNull(int index) {
return baseArgs.isNull(index);
}
// The interesting custom helpers.
public byte[] getArrayBuffer(int index) throws JSONException {
String encoded = baseArgs.getString(index);
return Base64.decode(encoded, Base64.DEFAULT);
}
}

View File

@@ -385,6 +385,11 @@ public class CordovaChromeClient extends WebChromeClient {
}
public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
this.openFileChooser(uploadMsg, acceptType, null);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
{
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);

View File

@@ -230,6 +230,10 @@ public class CordovaWebViewClient extends WebViewClient {
AuthenticationToken token = this.getAuthenticationToken(host, realm);
if (token != null) {
handler.proceed(token.getUserName(), token.getPassword());
}
else {
// Handle 401 like we'd normally do!
super.onReceivedHttpAuthRequest(view, handler, host, realm);
}
}

View File

@@ -39,7 +39,7 @@ import android.telephony.TelephonyManager;
public class Device extends CordovaPlugin {
public static final String TAG = "Device";
public static String cordovaVersion = "2.3.0"; // Cordova version
public static String cordovaVersion = "2.4.0rc2"; // Cordova version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID

View File

@@ -261,7 +261,7 @@ public class DroidGap extends Activity implements CordovaInterface {
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
Config.init(this);
LOG.d(TAG, "DroidGap.onCreate()");
super.onCreate(savedInstanceState);

View File

@@ -20,24 +20,28 @@ package org.apache.cordova;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
public class Echo extends CordovaPlugin {
@Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
final String result = args.isNull(0) ? null : args.getString(0);
public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
if ("echo".equals(action)) {
final String result = args.isNull(0) ? null : args.getString(0);
callbackContext.success(result);
return true;
} else if ("echoAsync".equals(action)) {
final String result = args.isNull(0) ? null : args.getString(0);
cordova.getThreadPool().execute(new Runnable() {
public void run() {
callbackContext.success(result);
}
});
return true;
} else if ("echoArrayBuffer".equals(action)) {
final byte[] result = args.getArrayBuffer(0);
callbackContext.success(result);
return true;
}
return false;
}

View File

@@ -215,6 +215,8 @@ public class FileTransfer extends CordovaPlugin {
HttpURLConnection conn = null;
HostnameVerifier oldHostnameVerifier = null;
SSLSocketFactory oldSocketFactory = null;
int totalBytes = 0;
int fixedLength = -1;
try {
// Create return object
FileUploadResult result = new FileUploadResult();
@@ -320,7 +322,6 @@ public class FileTransfer extends CordovaPlugin {
int stringLength = extraBytes.length + midParams.length() + tailParams.length() + fileNameBytes.length;
Log.d(LOG_TAG, "String Length: " + stringLength);
int fixedLength = -1;
if (sourceInputStream instanceof FileInputStream) {
fixedLength = (int) ((FileInputStream)sourceInputStream).getChannel().size() + stringLength;
progress.setLengthComputable(true);
@@ -363,13 +364,12 @@ public class FileTransfer extends CordovaPlugin {
// read file and write it into form...
int bytesRead = sourceInputStream.read(buffer, 0, bufferSize);
long totalBytes = 0;
long prevBytesRead = 0;
while (bytesRead > 0) {
totalBytes += bytesRead;
result.setBytesSent(totalBytes);
dos.write(buffer, 0, bufferSize);
dos.write(buffer, 0, bytesRead);
if (totalBytes > prevBytesRead + 102400) {
prevBytesRead = totalBytes;
Log.d(LOG_TAG, "Uploaded " + totalBytes + " of " + fixedLength + " bytes");
@@ -436,6 +436,7 @@ public class FileTransfer extends CordovaPlugin {
} catch (IOException e) {
JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn);
Log.e(LOG_TAG, error.toString(), e);
Log.e(LOG_TAG, "Failed after uploading " + totalBytes + " of " + fixedLength + " bytes.");
context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);

View File

@@ -130,7 +130,8 @@ public class NativeToJsMessageQueue {
}
private void packMessage(JsMessage message, StringBuilder sb) {
sb.append(message.calculateEncodedLength())
int len = message.calculateEncodedLength();
sb.append(len)
.append(' ');
message.encodeAsMessage(sb);
}
@@ -166,7 +167,8 @@ public class NativeToJsMessageQueue {
// Attach a char to indicate that there are more messages pending.
sb.append('*');
}
return sb.toString();
String ret = sb.toString();
return ret;
}
}
@@ -209,7 +211,8 @@ public class NativeToJsMessageQueue {
for (int i = willSendAllMessages ? 1 : 0; i < numMessagesToSend; ++i) {
sb.append('}');
}
return sb.toString();
String ret = sb.toString();
return ret;
}
}
@@ -406,6 +409,9 @@ public class NativeToJsMessageQueue {
case PluginResult.MESSAGE_TYPE_STRING: // s
ret += 1 + pluginResult.getStrMessage().length();
break;
case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
ret += 1 + pluginResult.getMessage().length();
break;
case PluginResult.MESSAGE_TYPE_JSON:
default:
ret += pluginResult.getMessage().length();
@@ -445,6 +451,10 @@ public class NativeToJsMessageQueue {
sb.append('s');
sb.append(pluginResult.getStrMessage());
break;
case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
sb.append('A');
sb.append(pluginResult.getMessage());
break;
case PluginResult.MESSAGE_TYPE_JSON:
default:
sb.append(pluginResult.getMessage()); // [ or {

View File

@@ -71,6 +71,15 @@ public class CallbackContext {
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
}
/**
* Helper for success callbacks that just returns the Status.OK by default
*
* @param message The message to add to the success result.
*/
public void success(byte[] message) {
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
}
/**
* Helper for success callbacks that just returns the Status.OK by default
*

View File

@@ -18,12 +18,12 @@
*/
package org.apache.cordova.api;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
/**
* Plugins must extend this class and override one of the execute methods.
*/
@@ -76,9 +76,28 @@ public class CordovaPlugin {
* @return Whether the action was valid.
*/
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
CordovaArgs cordovaArgs = new CordovaArgs(args);
return execute(action, cordovaArgs, callbackContext);
}
/**
* Executes the request.
*
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
* cordova.getThreadPool().execute(runnable);
*
* To run on the UI thread, use:
* cordova.getActivity().runOnUiThread(runnable);
*
* @param action The action to execute.
* @param args The exec() arguments, wrapped with some Cordova helpers.
* @param callbackContext The callback context used when calling back into JavaScript.
* @return Whether the action was valid.
*/
public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
return false;
}
/**
* Called when the system is about to start resuming a previous activity.
*

View File

@@ -21,6 +21,8 @@ package org.apache.cordova.api;
import org.json.JSONArray;
import org.json.JSONObject;
import android.util.Base64;
public class PluginResult {
private final int status;
private final int messageType;
@@ -68,6 +70,12 @@ public class PluginResult {
this.encodedMessage = Boolean.toString(b);
}
public PluginResult(Status status, byte[] data) {
this.status = status.ordinal();
this.messageType = MESSAGE_TYPE_ARRAYBUFFER;
this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP);
}
public void setKeepCallback(boolean b) {
this.keepCallback = b;
}
@@ -79,7 +87,7 @@ public class PluginResult {
public int getMessageType() {
return messageType;
}
public String getMessage() {
if (encodedMessage == null) {
encodedMessage = JSONObject.quote(strMessage);
@@ -134,7 +142,8 @@ public class PluginResult {
public static final int MESSAGE_TYPE_NUMBER = 3;
public static final int MESSAGE_TYPE_BOOLEAN = 4;
public static final int MESSAGE_TYPE_NULL = 5;
public static final int MESSAGE_TYPE_ARRAYBUFFER = 6;
public static String[] StatusMessages = new String[] {
"No result",
"OK",

View File

@@ -18,7 +18,7 @@
under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="org.apache.cordova.test" android:versionName="1.1" android:versionCode="5">
package="org.apache.cordova.test" android:versionName="1.0" android:versionCode="1">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"

File diff suppressed because it is too large Load Diff

View File

@@ -8,5 +8,5 @@
# project structure.
# Project target.
target=android-16
target=android-17
android.library.reference.1=../framework

View File

@@ -21,14 +21,72 @@ package org.apache.cordova.test;
*/
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.test.util.Purity;
import org.apache.cordova.test.actions.iframe;
import android.app.Activity;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.test.TouchUtils;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class IFrameTest extends ActivityInstrumentationTestCase2<iframe> {
public class IFrameTest extends ActivityInstrumentationTestCase2 {
public IFrameTest() {
super("org.apache.cordova.test",iframe.class);
}
private Instrumentation mInstr;
private Activity testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private CordovaWebView testView;
private TouchUtils touch;
private Purity touchTool;
public IFrameTest() {
super("org.apache.cordova.test",iframe.class);
}
protected void setUp() throws Exception {
super.setUp();
mInstr = this.getInstrumentation();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = (CordovaWebView) innerContainer.getChildAt(0);
touch = new TouchUtils();
touchTool = new Purity(testActivity, getInstrumentation());
}
public void testIframeDest()
{
testView.sendJavascript("loadUrl('http://maps.google.com/maps?output=embed');");
sleep(3000);
testView.sendJavascript("loadUrl('index2.html')");
sleep(1000);
String url = testView.getUrl();
assertTrue(url.endsWith("index.html"));
}
public void testIframeHistory()
{
testView.sendJavascript("loadUrl('http://maps.google.com/maps?output=embed');");
sleep(3000);
testView.sendJavascript("loadUrl('index2.html')");
sleep(1000);
String url = testView.getUrl();
testView.backHistory();
sleep(1000);
assertTrue(url.endsWith("index.html"));
}
private void sleep(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@@ -21,15 +21,55 @@ package org.apache.cordova.test;
*/
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.test.util.Purity;
import org.apache.cordova.test.actions.jqmtabbackbutton;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class JQMTabTest extends ActivityInstrumentationTestCase2<jqmtabbackbutton> {
public JQMTabTest(Class<jqmtabbackbutton> activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
private Instrumentation mInstr;
private jqmtabbackbutton testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private CordovaWebView testView;
private Purity touchTool;
public JQMTabTest()
{
super("org.apache.cordova.test.activity", jqmtabbackbutton.class);
}
protected void setUp() throws Exception {
super.setUp();
mInstr = this.getInstrumentation();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = (CordovaWebView) innerContainer.getChildAt(0);
touchTool = new Purity(testActivity, getInstrumentation());
}
public void testTouch()
{
sleep(5000);
int viewportHeight = touchTool.getViewportHeight() - 40;
int viewportWidth = touchTool.getViewportWidth();
touchTool.touch(50, viewportHeight);
sleep(10000);
}
private void sleep(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@@ -0,0 +1,171 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/*
* Purity is a small set of Android utility methods that allows us to simulate touch events on
* Android applications. This is important for simulating some of the most annoying tests.
*/
package org.apache.cordova.test.util;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Picture;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.webkit.WebView;
public class Purity {
Instrumentation inst;
int width, height;
float density;
Bitmap state;
boolean fingerDown = false;
public Purity(Context ctx, Instrumentation i)
{
inst = i;
DisplayMetrics display = ctx.getResources().getDisplayMetrics();
density = display.density;
width = display.widthPixels;
height = display.heightPixels;
}
/*
* WebKit doesn't give you real pixels anymore, this is done for subpixel fonts to appear on
* iOS and Android. However, Android automation requires real pixels
*/
private int getRealCoord(int coord)
{
return (int) (coord * density);
}
public int getViewportWidth()
{
return (int) (width/density);
}
public int getViewportHeight()
{
return (int) (height/density);
}
public void touch(int x, int y)
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
if(!fingerDown)
{
MotionEvent downEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(downEvent);
}
MotionEvent upEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, realX, realY, 0);
inst.sendPointerSync(upEvent);
}
public void touchStart(int x, int y)
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(event);
fingerDown = true;
}
//Move from the touch start
public void touchMove(int x, int y)
{
if(!fingerDown)
touchStart(x,y);
else
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, realX, realY, 0);
inst.sendPointerSync(event);
}
}
public void touchEnd(int x, int y)
{
if(!fingerDown)
{
touch(x, y);
}
else
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(event);
fingerDown = false;
}
}
public void setBitmap(WebView view)
{
Picture p = view.capturePicture();
state = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Bitmap.Config.ARGB_8888);
}
public boolean checkRenderView(WebView view)
{
if(state == null)
{
setBitmap(view);
return false;
}
else
{
Picture p = view.capturePicture();
Bitmap newState = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Bitmap.Config.ARGB_8888);
boolean result = newState.equals(state);
newState.recycle();
return result;
}
}
public void clearBitmap()
{
if(state != null)
state.recycle();
}
protected void finalize()
{
clearBitmap();
}
}