Merge branch 'master' of github.com:phonegap/phonegap-android

This commit is contained in:
Dave Johnson 2011-06-30 13:43:06 -07:00
commit 941b64f6a2
25 changed files with 632 additions and 234 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ local.properties
framework/phonegap.jar
framework/bin
framework/assets/www/.DS_Store
.DS_Store

View File

@ -1 +1 @@
0.9.5
0.9.6.1

View File

@ -5,8 +5,8 @@
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>PhoneGap</title>
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8">
<script type="text/javascript" charset="utf-8" src="phonegap.0.9.5.min.js"></script>
<script type="text/javascript" charset="utf-8" src="main.js"></script>
<script type="text/javascript" charset="utf-8" src="phonegap.0.9.6.1.min.js"></script>
<script type="text/javascript" charset="utf-8" src="main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
@ -31,8 +31,8 @@
<a href="#" class="btn large" onclick="show_pic();">Get a Picture</a>
<a href="#" class="btn large" onclick="get_contacts();">Get Phone's Contacts</a>
<a href="#" class="btn large" onclick="check_network();">Check Network</a>
<div id="viewport" class="viewport" style="display: none;">
<div id="viewport" class="viewport" style="display: none;">
<img style="width:60px;height:60px" id="test_img" src="" />
</div>
</div>
</body>
</html>

View File

@ -14,15 +14,16 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
@ -36,8 +37,11 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name">
<intent-filter>
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="2" />
<uses-sdk android:minSdkVersion="2" />
</manifest>

View File

@ -1044,7 +1044,7 @@ LocalFileSystem.prototype._castDate = function(pluginResult) {
file.type = pluginResult.message.type;
file.name = pluginResult.message.name;
file.fullPath = pluginResult.message.fullPath;
file.lastModifedDate = new Date(pluginResult.message.lastModifiedDate);
file.lastModifiedDate = new Date(pluginResult.message.lastModifiedDate);
pluginResult.message = file;
}
return pluginResult;

View File

@ -65,29 +65,49 @@ Network.prototype.isReachable = function(uri, callback, options) {
*/
var Connection = function() {
this.type = null;
this.homeNW = null;
this.currentNW = null;
this._firstRun = true;
this._timer = null;
this.timeout = 500;
var me = this;
this.getInfo(
function(info) {
me.type = info.type;
me.homeNW = info.homeNW;
me.currentNW = info.currentNW;
PhoneGap.onPhoneGapConnectionReady.fire();
function(type) {
// Need to send events if we are on or offline
if (type == "none") {
// set a timer if still offline at the end of timer send the offline event
me._timer = setTimeout(function(){
me.type = type;
PhoneGap.fireEvent('offline');
me._timer = null;
}, me.timeout);
} else {
// If there is a current offline event pending clear it
if (me._timer != null) {
clearTimeout(me._timer);
me._timer = null;
}
me.type = type;
PhoneGap.fireEvent('online');
}
// should only fire this once
if (me._firstRun) {
me._firstRun = false;
PhoneGap.onPhoneGapConnectionReady.fire();
}
},
function(e) {
console.log("Error initializing Network Connection: " + e);
});
};
Connection.UNKNOWN = 0;
Connection.ETHERNET = 1;
Connection.WIFI = 2;
Connection.CELL_2G = 3;
Connection.CELL_3G = 4;
Connection.CELL_4G = 5;
Connection.NONE = 20;
Connection.UNKNOWN = "unknown";
Connection.ETHERNET = "ethernet";
Connection.WIFI = "wifi";
Connection.CELL_2G = "2g";
Connection.CELL_3G = "3g";
Connection.CELL_4G = "4g";
Connection.NONE = "none";
/**
* Get connection info

View File

@ -99,7 +99,7 @@ PhoneGap.Channel.prototype.subscribe = function(f, c, g) {
if (f === null) { return; }
var func = f;
if (typeof c === "object" && f instanceof Function) { func = PhoneGap.close(c, f); }
if (typeof c === "object" && typeof f === "function") { func = PhoneGap.close(c, f); }
g = g || func.observer_guid || f.observer_guid || this.guid++;
func.observer_guid = g;
@ -120,7 +120,7 @@ PhoneGap.Channel.prototype.subscribeOnce = function(f, c) {
_this.unsubscribe(g);
};
if (this.fired) {
if (typeof c === "object" && f instanceof Function) { f = PhoneGap.close(c, f); }
if (typeof c === "object" && typeof f === "function") { f = PhoneGap.close(c, f); }
f.apply(this, this.fireArgs);
} else {
g = this.subscribe(m);
@ -132,7 +132,7 @@ PhoneGap.Channel.prototype.subscribeOnce = function(f, c) {
* Unsubscribes the function with the given guid from the channel.
*/
PhoneGap.Channel.prototype.unsubscribe = function(g) {
if (g instanceof Function) { g = g.observer_guid; }
if (typeof g === "function") { g = g.observer_guid; }
this.handlers[g] = null;
delete this.handlers[g];
};
@ -147,7 +147,7 @@ PhoneGap.Channel.prototype.fire = function(e) {
for (item in this.handlers) {
if (this.handlers.hasOwnProperty(item)) {
handler = this.handlers[item];
if (handler instanceof Function) {
if (typeof handler === "function") {
rv = (handler.apply(this, arguments) === false);
fail = fail || rv;
}
@ -344,10 +344,13 @@ PhoneGap.Channel.join(function() {
}
else {
var polling = prompt("usePolling", "gap_callbackServer:");
PhoneGap.UsePolling = polling;
if (polling == "true") {
PhoneGap.UsePolling = true;
PhoneGap.JSCallbackPolling();
}
else {
PhoneGap.UsePolling = false;
PhoneGap.JSCallback();
}
}
@ -507,7 +510,7 @@ PhoneGap.clone = function(obj) {
return retVal;
}
if (obj instanceof Function) {
if (typeof obj === "function") {
return obj;
}
@ -767,8 +770,8 @@ PhoneGap.JSCallback = function() {
// If callback has JavaScript statement to execute
if (xmlhttp.status === 200) {
// Need to url decode the response and replace %20 with a space
var msg = decodeURIComponent(xmlhttp.responseText.replace(/\+/g, '%20'));
// Need to url decode the response
var msg = decodeURIComponent(xmlhttp.responseText);
setTimeout(function() {
try {
var t = eval(msg);
@ -802,13 +805,11 @@ PhoneGap.JSCallback = function() {
console.log("JSCallback Error: Bad request. Stopping callbacks.");
}
// If error, restart callback server
// If error, revert to polling
else {
console.log("JSCallback Error: Request failed.");
prompt("restartServer", "gap_callbackServer:");
PhoneGap.JSCallbackPort = null;
PhoneGap.JSCallbackToken = null;
setTimeout(PhoneGap.JSCallback, 100);
PhoneGap.UsePolling = true;
PhoneGap.JSCallbackPolling();
}
}
};
@ -935,7 +936,11 @@ PhoneGap.includeJavascript = function(jsfile, successCallback) {
*/
var PluginManager = {
addService: function(serviceType, className) {
navigator.app.addService(serviceType, className);
try {
navigator.app.addService(serviceType, className);
} catch (e) {
console.log("Error adding service "+serviceType+": "+e);
}
}
};

View File

@ -1,7 +1,7 @@
<html>
<head>
<title></title>
<script src="phonegap.0.9.5.min.js"></script>
<script src="phonegap.0.9.6.1.min.js"></script>
</head>
<body>

View File

@ -10,5 +10,5 @@
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
target=android-8
target=android-12
apk-configurations=

View File

@ -12,6 +12,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import java.util.HashMap;
/**
* This class exposes methods in DroidGap that can be called from JavaScript.
@ -83,8 +84,11 @@ public class App extends Plugin {
public void loadUrl(String url, JSONObject props) throws JSONException {
System.out.println("App.loadUrl("+url+","+props+")");
int wait = 0;
boolean usePhoneGap = true;
boolean clearPrev = false;
// If there are properties, then set them on the Activity
HashMap<String, Object> params = new HashMap<String, Object>();
if (props != null) {
JSONArray keys = props.names();
for (int i=0; i<keys.length(); i++) {
@ -92,31 +96,42 @@ public class App extends Plugin {
if (key.equals("wait")) {
wait = props.getInt(key);
}
else if (key.equalsIgnoreCase("usephonegap")) {
usePhoneGap = props.getBoolean(key);
}
else if (key.equalsIgnoreCase("clearprev")) {
clearPrev = props.getBoolean(key);
}
else {
Object value = props.get(key);
if (value == null) {
}
else if (value.getClass().equals(String.class)) {
this.ctx.getIntent().putExtra(key, (String)value);
params.put(key, (String)value);
}
else if (value.getClass().equals(Boolean.class)) {
this.ctx.getIntent().putExtra(key, (Boolean)value);
params.put(key, (Boolean)value);
}
else if (value.getClass().equals(Integer.class)) {
this.ctx.getIntent().putExtra(key, (Integer)value);
params.put(key, (Integer)value);
}
}
}
}
// If wait property, then delay loading
if (wait > 0) {
((DroidGap)this.ctx).loadUrl(url, wait);
}
else {
((DroidGap)this.ctx).loadUrl(url);
try {
synchronized(this) {
this.wait(wait);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
((DroidGap)this.ctx).showWebPage(url, usePhoneGap, clearPrev, params);
}
/**

View File

@ -73,12 +73,12 @@ public class AudioHandler extends Plugin {
this.stopPlayingAudio(args.getString(0));
}
else if (action.equals("getCurrentPositionAudio")) {
long l = this.getCurrentPositionAudio(args.getString(0));
return new PluginResult(status, l);
float f = this.getCurrentPositionAudio(args.getString(0));
return new PluginResult(status, f);
}
else if (action.equals("getDurationAudio")) {
long l = this.getDurationAudio(args.getString(0), args.getString(1));
return new PluginResult(status, l);
float f = this.getDurationAudio(args.getString(0), args.getString(1));
return new PluginResult(status, f);
}
else if (action.equals("release")) {
boolean b = this.release(args.getString(0));
@ -230,10 +230,10 @@ public class AudioHandler extends Plugin {
* @param id The id of the audio player
* @return position in msec
*/
public long getCurrentPositionAudio(String id) {
public float getCurrentPositionAudio(String id) {
AudioPlayer audio = this.players.get(id);
if (audio != null) {
return(audio.getCurrentPosition());
return(audio.getCurrentPosition()/1000.0f);
}
return -1;
}
@ -245,7 +245,7 @@ public class AudioHandler extends Plugin {
* @param file The name of the audio file.
* @return The duration in msec.
*/
public long getDurationAudio(String id, String file) {
public float getDurationAudio(String id, String file) {
// Get audio file
AudioPlayer audio = this.players.get(id);

View File

@ -15,6 +15,7 @@ import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaRecorder;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Environment;
/**
* This class implements the audio playback and recording capabilities used by PhoneGap.
@ -53,7 +54,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
private String id; // The id of this player (used to identify Media object in JavaScript)
private int state = MEDIA_NONE; // State of recording or playback
private String audioFile = null; // File name to play or record to
private long duration = -1; // Duration of audio
private float duration = -1; // Duration of audio
private MediaRecorder recorder = null; // Audio recording object
private String tempFile = null; // Temporary recording file name
@ -70,10 +71,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
public AudioPlayer(AudioHandler handler, String id) {
this.handler = handler;
this.id = id;
// YES, I know this is bad, but I can't do it the right way because Google didn't have the
// foresight to add android.os.environment.getExternalDataDirectory until Android 2.2
this.tempFile = "/sdcard/tmprecording.mp3";
this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3";
}
/**
@ -209,7 +207,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
this.mPlayer.prepare();
// Get duration
this.duration = this.mPlayer.getDuration();
this.duration = getDurationInSeconds();
}
}
catch (Exception e) {
@ -319,7 +317,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
* -1=can't be determined
* -2=not allowed
*/
public long getDuration(String file) {
public float getDuration(String file) {
// Can't get duration of recording
if (this.recorder != null) {
@ -362,7 +360,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
}
// Save off duration
this.duration = this.mPlayer.getDuration();
this.duration = getDurationInSeconds();
this.prepareOnly = false;
// Send status notification to JavaScript
@ -370,6 +368,15 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
}
/**
* By default Android returns the length of audio in mills but we want seconds
*
* @return length of clip in seconds
*/
private float getDurationInSeconds() {
return (this.mPlayer.getDuration() / 1000.0f);
}
/**
* Callback to be invoked when there has been an error during an asynchronous operation
* (other errors will throw exceptions at method call time).

View File

@ -11,11 +11,14 @@ import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLEncoder;
import java.util.LinkedList;
import android.util.Log;
/**
* This class provides a way for Java to run JavaScript in the web page that has loaded PhoneGap.
* The CallbackServer class implements an XHR server and a polling server with a list of JavaScript
@ -42,6 +45,8 @@ import java.util.LinkedList;
*/
public class CallbackServer implements Runnable {
private static final String LOG_TAG = "CallbackServer";
/**
* The list of JavaScript statements to be sent to JavaScript.
*/
@ -224,8 +229,9 @@ public class CallbackServer implements Runnable {
//System.out.println("CallbackServer -- sending item");
response = "HTTP/1.1 200 OK\r\n\r\n";
String js = this.getJavascript();
if (js != null)
response += URLEncoder.encode(js, "UTF-8");
if (js != null) {
response += encode(js, "UTF-8");
}
}
}
else {
@ -321,4 +327,81 @@ public class CallbackServer implements Runnable {
}
}
/* The Following code has been modified from original implementation of URLEncoder */
/* start */
/*
* 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.
*/
static final String digits = "0123456789ABCDEF";
/**
* This will encode the return value to JavaScript. We revert the encoding for
* common characters that don't require encoding to reduce the size of the string
* being passed to JavaScript.
*
* @param s to be encoded
* @param enc encoding type
* @return encoded string
*/
public static String encode(String s, String enc) throws UnsupportedEncodingException {
if (s == null || enc == null) {
throw new NullPointerException();
}
// check for UnsupportedEncodingException
"".getBytes(enc);
// Guess a bit bigger for encoded form
StringBuilder buf = new StringBuilder(s.length() + 16);
int start = -1;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
|| (ch >= '0' && ch <= '9')
|| " .-*_'(),<>=?@[]{}:~\"\\/;!".indexOf(ch) > -1) {
if (start >= 0) {
convert(s.substring(start, i), buf, enc);
start = -1;
}
if (ch != ' ') {
buf.append(ch);
} else {
buf.append(' ');
}
} else {
if (start < 0) {
start = i;
}
}
}
if (start >= 0) {
convert(s.substring(start, s.length()), buf, enc);
}
return buf.toString();
}
private static void convert(String s, StringBuilder buf, String enc) throws UnsupportedEncodingException {
byte[] bytes = s.getBytes(enc);
for (int j = 0; j < bytes.length; j++) {
buf.append('%');
buf.append(digits.charAt((bytes[j] & 0xf0) >> 4));
buf.append(digits.charAt(bytes[j] & 0xf));
}
}
/* end */
}

View File

@ -166,7 +166,14 @@ public class CameraLauncher extends Plugin {
if (resultCode == Activity.RESULT_OK) {
try {
// Read in bitmap of captured image
Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getContentResolver(), imageUri);
Bitmap bitmap;
try {
bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getContentResolver(), imageUri);
} catch (FileNotFoundException e) {
Uri uri = intent.getData();
android.content.ContentResolver resolver = this.ctx.getContentResolver();
bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
}
// If sending base64 image back
if (destType == DATA_URL) {

View File

@ -178,11 +178,13 @@ public abstract class ContactAccessor {
protected String getJsonString(JSONObject obj, String property) {
String value = null;
try {
if (obj != null) {
value = obj.getString(property);
if (value.equals("null")) {
Log.d(LOG_TAG, property + " is string called 'null'");
value = null;
}
if (value.equals("null")) {
Log.d(LOG_TAG, property + " is string called 'null'");
value = null;
}
}
}
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get = " + e.getMessage());

View File

@ -1420,7 +1420,6 @@ public class ContactAccessorSdk5 extends ContactAccessor {
.build());
}
// Add urls
JSONArray websites = null;
try {
@ -1473,7 +1472,6 @@ public class ContactAccessorSdk5 extends ContactAccessor {
Log.e(LOG_TAG, e.getMessage(), e);
retVal = false;
}
return retVal;
}

View File

@ -14,13 +14,11 @@ import org.json.JSONObject;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import android.content.Context;
import android.provider.Settings;
import android.telephony.TelephonyManager;
public class Device extends Plugin {
public static String phonegapVersion = "0.9.5"; // PhoneGap version
public static String phonegapVersion = "0.9.6.1"; // PhoneGap version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
@ -116,34 +114,13 @@ public class Device extends Plugin {
public String getPhonegapVersion() {
return Device.phonegapVersion;
}
public String getLine1Number(){
TelephonyManager operator = (TelephonyManager)this.ctx.getSystemService(Context.TELEPHONY_SERVICE);
return operator.getLine1Number();
}
public String getDeviceId(){
TelephonyManager operator = (TelephonyManager)this.ctx.getSystemService(Context.TELEPHONY_SERVICE);
return operator.getDeviceId();
}
public String getSimSerialNumber(){
TelephonyManager operator = (TelephonyManager)this.ctx.getSystemService(Context.TELEPHONY_SERVICE);
return operator.getSimSerialNumber();
}
public String getSubscriberId(){
TelephonyManager operator = (TelephonyManager)this.ctx.getSystemService(Context.TELEPHONY_SERVICE);
return operator.getSubscriberId();
}
public String getModel()
{
public String getModel() {
String model = android.os.Build.MODEL;
return model;
}
public String getProductName()
{
public String getProductName() {
String productname = android.os.Build.PRODUCT;
return productname;
}
@ -158,8 +135,7 @@ public class Device extends Plugin {
return osversion;
}
public String getSDKVersion()
{
public String getSDKVersion() {
String sdkversion = android.os.Build.VERSION.SDK;
return sdkversion;
}

View File

@ -7,38 +7,49 @@
*/
package com.phonegap;
import java.util.HashMap;
import java.util.Map.Entry;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.Activity;
import android.app.AlertDialog;
import android.widget.EditText;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.media.AudioManager;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.GeolocationPermissions.Callback;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.GeolocationPermissions.Callback;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginManager;
import com.phonegap.api.PhonegapActivity;
/**
* This class is the main Android activity that represents the PhoneGap
@ -119,10 +130,15 @@ public class DroidGap extends PhonegapActivity {
protected boolean clearHistory = false;
// The initial URL for our app
// ie http://server/path/index.html#abc?query
private String url;
// The initial URL for our app up to and including the file name
// ie http://server/path/index.html
private String urlFile;
// The base of the initial URL for our app
private String baseUrl;
private String baseUrl = null;
// Plugin to call when activity result is received
protected Plugin activityResultCallback = null;
@ -168,7 +184,11 @@ public class DroidGap extends PhonegapActivity {
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket!
root = new LinearLayout(this);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
root = new LinearLayoutSoftKeyboardDetect(this, width, height);
root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(Color.BLACK);
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
@ -330,13 +350,16 @@ public class DroidGap extends PhonegapActivity {
*/
public void loadUrl(final String url) {
System.out.println("loadUrl("+url+")");
this.urlFile = this.getUrlFile(url);
this.url = url;
int i = url.lastIndexOf('/');
if (i > 0) {
this.baseUrl = url.substring(0, i);
}
else {
this.baseUrl = this.url;
if (this.baseUrl == null) {
int i = url.lastIndexOf('/');
if (i > 0) {
this.baseUrl = url.substring(0, i+1);
}
else {
this.baseUrl = this.url + "/";
}
}
System.out.println("url="+url+" baseUrl="+baseUrl);
@ -608,17 +631,28 @@ public class DroidGap extends PhonegapActivity {
// Send pause event to JavaScript
this.appView.loadUrl("javascript:try{PhoneGap.onPause.fire();}catch(e){};");
// Forward to plugins
this.pluginManager.onPause(this.keepRunning);
// If app doesn't want to run in background
if (!this.keepRunning) {
// Forward to plugins
this.pluginManager.onPause();
// Pause JavaScript timers (including setInterval)
this.appView.pauseTimers();
}
}
@Override
/**
* Called when the activity receives a new intent
**/
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
//Forward to plugins
this.pluginManager.onNewIntent(intent);
}
@Override
/**
* Called when the activity will start interacting with the user.
@ -632,6 +666,9 @@ public class DroidGap extends PhonegapActivity {
// Send resume event to JavaScript
this.appView.loadUrl("javascript:try{PhoneGap.onResume.fire();}catch(e){};");
// Forward to plugins
this.pluginManager.onResume(this.keepRunning || this.activityResultKeepRunning);
// If app doesn't want to run in background
if (!this.keepRunning || this.activityResultKeepRunning) {
@ -641,9 +678,6 @@ public class DroidGap extends PhonegapActivity {
this.activityResultKeepRunning = false;
}
// Forward to plugins
this.pluginManager.onResume();
// Resume JavaScript timers (including setInterval)
this.appView.resumeTimers();
}
@ -658,21 +692,18 @@ public class DroidGap extends PhonegapActivity {
if (this.appView != null) {
// Make sure pause event is sent if onPause hasn't been called before onDestroy
this.appView.loadUrl("javascript:try{PhoneGap.onPause.fire();}catch(e){};");
// Make sure pause event is sent if onPause hasn't been called before onDestroy
this.appView.loadUrl("javascript:try{PhoneGap.onPause.fire();}catch(e){};");
// Send destroy event to JavaScript
this.appView.loadUrl("javascript:try{PhoneGap.onDestroy.fire();}catch(e){};");
// Send destroy event to JavaScript
this.appView.loadUrl("javascript:try{PhoneGap.onDestroy.fire();}catch(e){};");
// Load blank page so that JavaScript onunload is called
this.appView.loadUrl("about:blank");
// Load blank page so that JavaScript onunload is called
this.appView.loadUrl("about:blank");
// Forward to plugins
this.pluginManager.onDestroy();
// Forward to plugins
this.pluginManager.onDestroy();
if (this.callbackServer != null) {
this.callbackServer.destroy();
}
}
}
@ -696,13 +727,82 @@ public class DroidGap extends PhonegapActivity {
this.callbackServer.sendJavascript(statement);
}
/**
* Return up to file part of url.
* If url = http://server/page.html#abc, then return http://server/page.html
*
* @param url
* @return
*/
private String getUrlFile(String url) {
int p1 = url.indexOf("#");
int p2 = url.indexOf("?");
if (p1 < 0) p1 = url.length();
if (p2 < 0) p2 = url.length();
int p3 = (p1 < p2) ? p1 : p2;
return url.substring(0, p3);
}
/**
* Display a new browser with the specified URL.
*
* NOTE: If usePhoneGap is set, only trusted PhoneGap URLs should be loaded,
* since any PhoneGap API can be called by the loaded HTML page.
*
* @param url The url to load.
* @param usePhoneGap Load url in PhoneGap webview.
* @param clearPrev Clear the activity stack, so new app becomes top of stack
* @param params DroidGap parameters for new app
* @throws android.content.ActivityNotFoundException
*/
public void showWebPage(String url, boolean usePhoneGap, boolean clearPrev, HashMap<String, Object> params) throws android.content.ActivityNotFoundException {
Intent intent = null;
if (usePhoneGap) {
intent = new Intent().setClass(this, com.phonegap.DroidGap.class);
intent.putExtra("url", url);
// Add parameters
if (params != null) {
java.util.Set<Entry<String,Object>> s = params.entrySet();
java.util.Iterator<Entry<String,Object>> it = s.iterator();
while(it.hasNext()) {
Entry<String,Object> entry = it.next();
String key = entry.getKey();
Object value = entry.getValue();
if (value == null) {
}
else if (value.getClass().equals(String.class)) {
intent.putExtra(key, (String)value);
}
else if (value.getClass().equals(Boolean.class)) {
intent.putExtra(key, (Boolean)value);
}
else if (value.getClass().equals(Integer.class)) {
intent.putExtra(key, (Integer)value);
}
}
}
}
else {
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
}
this.startActivity(intent);
// Finish current activity
if (clearPrev) {
this.finish();
}
}
/**
* Provides a hook for calling "alert" from javascript. Useful for
* debugging your javascript.
*/
public class GapClient extends WebChromeClient {
private Context ctx;
private DroidGap ctx;
/**
* Constructor.
@ -710,7 +810,7 @@ public class DroidGap extends PhonegapActivity {
* @param ctx
*/
public GapClient(Context ctx) {
this.ctx = ctx;
this.ctx = (DroidGap)ctx;
}
/**
@ -782,10 +882,17 @@ public class DroidGap extends PhonegapActivity {
*/
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// Security check to make sure any requests are coming from the page initially
// loaded in webview and not another loaded in an iframe.
boolean reqOk = false;
if (url.indexOf(this.ctx.baseUrl) == 0) {
reqOk = true;
}
// Calling PluginManager.exec() to call a native service using
// prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
if (defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
JSONArray array;
try {
array = new JSONArray(defaultValue.substring(4));
@ -801,13 +908,13 @@ public class DroidGap extends PhonegapActivity {
}
// Polling for JavaScript messages
else if (defaultValue.equals("gap_poll:")) {
else if (reqOk && defaultValue.equals("gap_poll:")) {
String r = callbackServer.getJavascript();
result.confirm(r);
}
// Calling into CallbackServer
else if (defaultValue.equals("gap_callbackServer:")) {
else if (reqOk && defaultValue.equals("gap_callbackServer:")) {
String r = "";
if (message.equals("usePolling")) {
r = ""+callbackServer.usePolling();
@ -1022,17 +1129,18 @@ public class DroidGap extends PhonegapActivity {
// All else
else {
int i = url.lastIndexOf('/');
String newBaseUrl = url;
if (i > 0) {
newBaseUrl = url.substring(0, i);
}
// If our app or file:, then load into our webview
// NOTE: This replaces our app with new URL. When BACK is pressed,
// our app is reloaded and restarted. All state is lost.
if (this.ctx.loadInWebView || url.startsWith("file://") || this.ctx.baseUrl.equals(newBaseUrl)) {
this.ctx.appView.loadUrl(url);
if (this.ctx.loadInWebView || url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0) {
try {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("loadingDialog", "");
params.put("hideLoadingDialogOnPageLoad", true);
this.ctx.showWebPage(url, true, false, params);
} catch (android.content.ActivityNotFoundException e) {
System.out.println("Error loading url into DroidGap - "+url+":"+ e.toString());
}
}
// If not our application, let default viewer handle
@ -1065,7 +1173,9 @@ public class DroidGap extends PhonegapActivity {
// Try firing the onNativeReady event in JS. If it fails because the JS is
// not loaded yet then just set a flag so that the onNativeReady can be fired
// from the JS side when the JS gets to that code.
appView.loadUrl("javascript:try{ PhoneGap.onNativeReady.fire();}catch(e){_nativeReady = true;}");
if (!url.equals("about:blank")) {
appView.loadUrl("javascript:try{ PhoneGap.onNativeReady.fire();}catch(e){_nativeReady = true;}");
}
// Make app view visible
appView.setVisibility(View.VISIBLE);
@ -1081,6 +1191,13 @@ public class DroidGap extends PhonegapActivity {
this.ctx.clearHistory = false;
this.ctx.appView.clearHistory();
}
// Shutdown if blank loaded
if (url.equals("about:blank")) {
if (this.ctx.callbackServer != null) {
this.ctx.callbackServer.destroy();
}
}
}
/**
@ -1105,6 +1222,27 @@ public class DroidGap extends PhonegapActivity {
// Handle error
this.ctx.onReceivedError(errorCode, description, failingUrl);
}
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final String packageName = this.ctx.getPackageName();
final PackageManager pm = this.ctx.getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// debug = true
handler.proceed();
return;
} else {
// debug = false
super.onReceivedSslError(view, handler, error);
}
} catch (NameNotFoundException e) {
// When it doubt, lock it out!
super.onReceivedSslError(view, handler, error);
}
}
}
/**
@ -1125,6 +1263,7 @@ public class DroidGap extends PhonegapActivity {
// If back key is bound, then send event to JavaScript
if (this.bound) {
this.appView.loadUrl("javascript:PhoneGap.fireEvent('backbutton');");
return true;
}
// If not bound
@ -1133,6 +1272,7 @@ public class DroidGap extends PhonegapActivity {
// Go to previous page in webview if it is possible to go back
if (this.appView.canGoBack()) {
this.appView.goBack();
return true;
}
// If not, then invoke behavior of super class
@ -1145,11 +1285,13 @@ public class DroidGap extends PhonegapActivity {
// If menu key
else if (keyCode == KeyEvent.KEYCODE_MENU) {
this.appView.loadUrl("javascript:PhoneGap.fireEvent('menubutton');");
return true;
}
// If search key
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
this.appView.loadUrl("javascript:PhoneGap.fireEvent('searchbutton');");
return true;
}
return false;
@ -1276,4 +1418,84 @@ public class DroidGap extends PhonegapActivity {
}
});
}
/**
* We are providing this class to detect when the soft keyboard is shown
* and hidden in the web view.
*/
class LinearLayoutSoftKeyboardDetect extends LinearLayout {
private static final String LOG_TAG = "SoftKeyboardDetect";
private int oldHeight = 0; // Need to save the old height as not to send redundant events
private int oldWidth = 0; // Need to save old width for orientation change
private int screenWidth = 0;
private int screenHeight = 0;
public LinearLayoutSoftKeyboardDetect(Context context, int width, int height) {
super(context);
screenWidth = width;
screenHeight = height;
}
@Override
/**
* Start listening to new measurement events. Fire events when the height
* gets smaller fire a show keyboard event and when height gets bigger fire
* a hide keyboard event.
*
* Note: We are using callbackServer.sendJavascript() instead of
* this.appView.loadUrl() as changing the URL of the app would cause the
* soft keyboard to go away.
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.d(LOG_TAG, "We are in our onMeasure method");
// Get the current height of the visible part of the screen.
// This height will not included the status bar.
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
Log.d(LOG_TAG, "Old Height = " + oldHeight);
Log.d(LOG_TAG, "Height = " + height);
Log.d(LOG_TAG, "Old Width = " + oldWidth);
Log.d(LOG_TAG, "Width = " + width);
// If the oldHeight = 0 then this is the first measure event as the app starts up.
// If oldHeight == height then we got a measurement change that doesn't affect us.
if (oldHeight == 0 || oldHeight == height) {
Log.d(LOG_TAG, "Ignore this event");
}
// Account for orientation change and ignore this event/Fire orientation change
else if(screenHeight == width)
{
int tmp_var = screenHeight;
screenHeight = screenWidth;
screenWidth = tmp_var;
Log.d(LOG_TAG, "Orientation Change");
}
// If the height as gotten bigger then we will assume the soft keyboard has
// gone away.
else if (height > oldHeight) {
Log.d(LOG_TAG, "Throw hide keyboard event");
callbackServer.sendJavascript("PhoneGap.fireEvent('hidekeyboard');");
}
// If the height as gotten smaller then we will assume the soft keyboard has
// been displayed.
else if (height < oldHeight) {
Log.d(LOG_TAG, "Throw show keyboard event");
callbackServer.sendJavascript("PhoneGap.fireEvent('showkeyboard');");
}
// Update the old height for the next event
oldHeight = height;
oldWidth = width;
}
}
}

View File

@ -10,6 +10,7 @@ package com.phonegap;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.channels.FileChannel;
import org.apache.commons.codec.binary.Base64;
@ -229,15 +230,16 @@ public class FileUtils extends Plugin {
* @throws JSONException
*/
private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException {
String decoded = URLDecoder.decode(url, "UTF-8");
// Test to see if this is a valid URL first
@SuppressWarnings("unused")
URL testUrl = new URL(url);
@SuppressWarnings("unused")
URL testUrl = new URL(decoded);
File fp = null;
if (url.startsWith("file://")) {
fp = new File(url.substring(7, url.length()));
if (decoded.startsWith("file://")) {
fp = new File(decoded.substring(7, decoded.length()));
} else {
fp = new File(url);
fp = new File(decoded);
}
if (!fp.exists()) {
throw new FileNotFoundException();
@ -411,7 +413,7 @@ public class FileUtils extends Plugin {
}
// Check to make sure we are not copying the directory into itself
if (destinationDir.getAbsolutePath().startsWith(srcDir.getAbsolutePath())) {
if (isCopyOnItself(srcDir.getAbsolutePath(), destinationDir.getAbsolutePath())) {
throw new InvalidModificationException("Can't copy itself into itself");
}
@ -435,6 +437,26 @@ public class FileUtils extends Plugin {
return getEntry(destinationDir);
}
/**
* Check to see if the user attempted to copy an entry into its parent without changing its name,
* or attempted to copy a directory into a directory that it contains directly or indirectly.
*
* @param srcDir
* @param destinationDir
* @return
*/
private boolean isCopyOnItself(String src, String dest) {
// This weird test is to determine if we are copying or moving a directory into itself.
// Copy /sdcard/myDir to /sdcard/myDir-backup is okay but
// Copy /sdcard/myDir to /sdcard/myDir/backup should thow an INVALID_MODIFICATION_ERR
if (dest.startsWith(src) && dest.indexOf(File.separator, src.length()-1) != -1) {
return true;
}
return false;
}
/**
* Move a file
*
@ -480,8 +502,8 @@ public class FileUtils extends Plugin {
}
// Check to make sure we are not copying the directory into itself
if (destinationDir.getAbsolutePath().startsWith(srcDir.getAbsolutePath())) {
throw new InvalidModificationException("Can't copy itself into itself");
if (isCopyOnItself(srcDir.getAbsolutePath(), destinationDir.getAbsolutePath())) {
throw new InvalidModificationException("Can't move itself into itself");
}
// If the destination directory already exists and is empty then delete it. This is according to spec.

View File

@ -11,7 +11,6 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin;
@ -21,13 +20,13 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.*;
import android.telephony.TelephonyManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
public class NetworkManager extends Plugin {
public static int NOT_REACHABLE = 0;
public static int NOT_REACHABLE = 0;
public static int REACHABLE_VIA_CARRIER_DATA_NETWORK = 1;
public static int REACHABLE_VIA_WIFI_NETWORK = 2;
@ -46,24 +45,26 @@ public class NetworkManager extends Plugin {
public static final String LTE = "lte";
public static final String UMB = "umb";
// return types
public static final int TYPE_UNKNOWN = 0;
public static final int TYPE_ETHERNET = 1;
public static final int TYPE_WIFI = 2;
public static final int TYPE_2G = 3;
public static final int TYPE_3G = 4;
public static final int TYPE_4G = 5;
public static final int TYPE_NONE = 20;
public static final String TYPE_UNKNOWN = "unknown";
public static final String TYPE_ETHERNET = "ethernet";
public static final String TYPE_WIFI = "wifi";
public static final String TYPE_2G = "2g";
public static final String TYPE_3G = "3g";
public static final String TYPE_4G = "4g";
public static final String TYPE_NONE = "none";
private static final String LOG_TAG = "NetworkManager";
private String connectionCallbackId;
ConnectivityManager sockMan;
TelephonyManager telephonyManager;
ConnectivityManager sockMan;
BroadcastReceiver receiver;
/**
* Constructor.
*/
public NetworkManager() {
this.receiver = null;
}
/**
@ -75,19 +76,23 @@ public class NetworkManager extends Plugin {
public void setContext(PhonegapActivity ctx) {
super.setContext(ctx);
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
this.telephonyManager = ((TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE));
this.connectionCallbackId = null;
// We need to listen to connectivity events to update navigator.connection
IntentFilter intentFilter = new IntentFilter() ;
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
ctx.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
}
}, intentFilter);
}
if (this.receiver == null) {
this.receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
}
};
ctx.registerReceiver(this.receiver, intentFilter);
}
}
/**
* Executes the request and returns PluginResult.
*
@ -135,6 +140,19 @@ public class NetworkManager extends Plugin {
// All methods take a while, so always use async
return false;
}
/**
* Stop network receiver.
*/
public void onDestroy() {
if (this.receiver != null) {
try {
this.ctx.unregisterReceiver(this.receiver);
} catch (Exception e) {
Log.e(LOG_TAG, "Error unregistering network receiver: " + e.getMessage(), e);
}
}
}
//--------------------------------------------------------------------------
// LOCAL METHODS
@ -147,11 +165,9 @@ public class NetworkManager extends Plugin {
* @param info the current active network info
* @return
*/
private void updateConnectionInfo(NetworkInfo info) {
JSONObject connection = this.getConnectionInfo(info);
// send update to javascript "navigator.connection"
sendUpdate(connection);
private void updateConnectionInfo(NetworkInfo info) {
// send update to javascript "navigator.network.connection"
sendUpdate(this.getConnectionInfo(info));
}
/**
@ -160,40 +176,18 @@ public class NetworkManager extends Plugin {
* @param info the current active network info
* @return a JSONObject that represents the network info
*/
private JSONObject getConnectionInfo(NetworkInfo info) {
JSONObject connection = new JSONObject();
try {
if (info != null) {
// If we are not connected to any network set type to none
if (!info.isConnected()) {
connection.put("type", TYPE_NONE);
connection.put("homeNW", null);
connection.put("currentNW", null);
}
else {
// If we are connected check which type
// First off is wifi
if (info.getTypeName().toLowerCase().equals(WIFI)) {
connection.put("type", TYPE_WIFI);
connection.put("homeNW", null);
connection.put("currentNW", null);
}
// Otherwise it must be one of the mobile network protocols
else {
// Determine the correct type, 2G, 3G, 4G
connection.put("type", getType(info));
connection.put("homeNW", telephonyManager.getSimOperatorName());
connection.put("currentNW", telephonyManager.getNetworkOperatorName());
}
}
private String getConnectionInfo(NetworkInfo info) {
String type = TYPE_NONE;
if (info != null) {
// If we are not connected to any network set type to none
if (!info.isConnected()) {
type = TYPE_NONE;
}
else {
type = getType(info);
}
}
catch (JSONException e) {
// this should never happen
Log.e(LOG_TAG, e.getMessage(), e);
}
return connection;
return type;
}
/**
@ -201,8 +195,8 @@ public class NetworkManager extends Plugin {
*
* @param connection the network info to set as navigator.connection
*/
private void sendUpdate(JSONObject connection) {
PluginResult result = new PluginResult(PluginResult.Status.OK, connection);
private void sendUpdate(String type) {
PluginResult result = new PluginResult(PluginResult.Status.OK, type);
result.setKeepCallback(true);
this.success(result, this.connectionCallbackId);
}
@ -213,11 +207,14 @@ public class NetworkManager extends Plugin {
* @param info the network info so we can determine connection type.
* @return the type of mobile network we are on
*/
private int getType(NetworkInfo info) {
private String getType(NetworkInfo info) {
if (info != null) {
String type = info.getTypeName();
if (type.toLowerCase().equals(MOBILE)) {
if (type.toLowerCase().equals(WIFI)) {
return TYPE_WIFI;
}
else if (type.toLowerCase().equals(MOBILE)) {
type = info.getSubtypeName();
if (type.toLowerCase().equals(GSM) ||
type.toLowerCase().equals(GPRS) ||
@ -278,7 +275,7 @@ public class NetworkManager extends Plugin {
public int isReachable(String uri, boolean isIpAddress) {
int reachable = NOT_REACHABLE;
if (uri.indexOf("http://") == -1) {
if (uri.indexOf("http://") == -1 && uri.indexOf("https://") == -1) {
uri = "http://" + uri;
}
@ -301,4 +298,4 @@ public class NetworkManager extends Plugin {
return reachable;
}
}
}

View File

@ -54,13 +54,17 @@ public interface IPlugin {
/**
* Called when the system is about to start resuming a previous activity.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
void onPause();
void onPause(boolean multitasking);
/**
* Called when the activity will start interacting with the user.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
void onResume();
void onResume(boolean multitasking);
/**
* The final call you receive before your activity is destroyed.

View File

@ -64,14 +64,24 @@ public abstract class Plugin implements IPlugin {
/**
* Called when the system is about to start resuming a previous activity.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onPause() {
public void onPause(boolean multitasking) {
}
/**
* Called when the activity will start interacting with the user.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onResume() {
public void onResume(boolean multitasking) {
}
/**
* Called when the activity receives a new intent.
*/
public void onNewIntent(Intent intent) {
}
/**

View File

@ -13,6 +13,7 @@ import java.util.Map.Entry;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
import android.webkit.WebView;
/**
@ -229,27 +230,31 @@ public final class PluginManager {
/**
* Called when the system is about to start resuming a previous activity.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onPause() {
public void onPause(boolean multitasking) {
java.util.Set<Entry<String,Plugin>> s = this.plugins.entrySet();
java.util.Iterator<Entry<String,Plugin>> it = s.iterator();
while(it.hasNext()) {
Entry<String,Plugin> entry = it.next();
Plugin plugin = entry.getValue();
plugin.onPause();
plugin.onPause(multitasking);
}
}
/**
* Called when the activity will start interacting with the user.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onResume() {
public void onResume(boolean multitasking) {
java.util.Set<Entry<String,Plugin>> s = this.plugins.entrySet();
java.util.Iterator<Entry<String,Plugin>> it = s.iterator();
while(it.hasNext()) {
Entry<String,Plugin> entry = it.next();
Plugin plugin = entry.getValue();
plugin.onResume();
plugin.onResume(multitasking);
}
}
@ -265,4 +270,17 @@ public final class PluginManager {
plugin.onDestroy();
}
}
/**
* Called when the activity receives a new intent.
*/
public void onNewIntent(Intent intent) {
java.util.Set<Entry<String,Plugin>> s = this.plugins.entrySet();
java.util.Iterator<Entry<String,Plugin>> it = s.iterator();
while(it.hasNext()) {
Entry<String,Plugin> entry = it.next();
Plugin plugin = entry.getValue();
plugin.onNewIntent(intent);
}
}
}

View File

@ -88,7 +88,7 @@ class Classic
# copies stuff from src directory into the android project directory (@path)
def copy_libs
version = IO.read(File.join(@framework_dir, '../VERSION'))
version = IO.read(File.join(@framework_dir, '../VERSION')).lstrip.rstrip
framework_res_dir = File.join(@framework_dir, "res")
app_res_dir = File.join(@path, "res")
# copies in the jar

View File

@ -33,12 +33,19 @@ class Update
# TODO need to allow for www import inc icon
def copy_libs
puts "Copying over libraries and assets..."
FileUtils.mkdir_p File.join(@path, "libs")
FileUtils.cp File.join(@framework_dir, "phonegap.jar"), File.join(@path, "libs")
version = IO.read(File.join(@framework_dir, '../VERSION'))
FileUtils.mkdir_p File.join(@path, "assets", "www")
FileUtils.cp File.join(@framework_dir, "assets", "www", "phonegap.js"), File.join(@path, "assets", "www")
FileUtils.cp File.join(@framework_dir, "phonegap.#{ version }.jar"), File.join(@path, "libs")
# concat JS and put into www folder. this can be overridden in the config.xml via @app_js_dir
js_dir = File.join(@framework_dir, "assets", "js")
phonegapjs = IO.read(File.join(js_dir, 'phonegap.js.base'))
Dir.new(js_dir).entries.each do |script|
next if script[0].chr == "." or script == "phonegap.js.base"
phonegapjs << IO.read(File.join(js_dir, script))
phonegapjs << "\n\n"
end
File.open(File.join(@path, "assets", "www", "phonegap.#{ version }.js"), 'w') {|f| f.write(phonegapjs) }
end
#
end