forked from github/cordova-android
Merge branch 'master' of github.com:phonegap/phonegap-android
This commit is contained in:
commit
941b64f6a2
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ local.properties
|
|||||||
framework/phonegap.jar
|
framework/phonegap.jar
|
||||||
framework/bin
|
framework/bin
|
||||||
framework/assets/www/.DS_Store
|
framework/assets/www/.DS_Store
|
||||||
|
.DS_Store
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||||
<title>PhoneGap</title>
|
<title>PhoneGap</title>
|
||||||
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8">
|
<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="phonegap.0.9.6.1.min.js"></script>
|
||||||
<script type="text/javascript" charset="utf-8" src="main.js"></script>
|
<script type="text/javascript" charset="utf-8" src="main.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
@ -14,15 +14,16 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<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_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
|
<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.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<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.MODIFY_AUDIO_SETTINGS" />
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<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" />
|
||||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||||
@ -36,8 +37,11 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name">
|
||||||
|
<intent-filter>
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="2" />
|
<uses-sdk android:minSdkVersion="2" />
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -1044,7 +1044,7 @@ LocalFileSystem.prototype._castDate = function(pluginResult) {
|
|||||||
file.type = pluginResult.message.type;
|
file.type = pluginResult.message.type;
|
||||||
file.name = pluginResult.message.name;
|
file.name = pluginResult.message.name;
|
||||||
file.fullPath = pluginResult.message.fullPath;
|
file.fullPath = pluginResult.message.fullPath;
|
||||||
file.lastModifedDate = new Date(pluginResult.message.lastModifiedDate);
|
file.lastModifiedDate = new Date(pluginResult.message.lastModifiedDate);
|
||||||
pluginResult.message = file;
|
pluginResult.message = file;
|
||||||
}
|
}
|
||||||
return pluginResult;
|
return pluginResult;
|
||||||
|
@ -65,29 +65,49 @@ Network.prototype.isReachable = function(uri, callback, options) {
|
|||||||
*/
|
*/
|
||||||
var Connection = function() {
|
var Connection = function() {
|
||||||
this.type = null;
|
this.type = null;
|
||||||
this.homeNW = null;
|
this._firstRun = true;
|
||||||
this.currentNW = null;
|
this._timer = null;
|
||||||
|
this.timeout = 500;
|
||||||
|
|
||||||
var me = this;
|
var me = this;
|
||||||
this.getInfo(
|
this.getInfo(
|
||||||
function(info) {
|
function(type) {
|
||||||
me.type = info.type;
|
// Need to send events if we are on or offline
|
||||||
me.homeNW = info.homeNW;
|
if (type == "none") {
|
||||||
me.currentNW = info.currentNW;
|
// 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();
|
PhoneGap.onPhoneGapConnectionReady.fire();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
function(e) {
|
function(e) {
|
||||||
console.log("Error initializing Network Connection: " + e);
|
console.log("Error initializing Network Connection: " + e);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Connection.UNKNOWN = 0;
|
Connection.UNKNOWN = "unknown";
|
||||||
Connection.ETHERNET = 1;
|
Connection.ETHERNET = "ethernet";
|
||||||
Connection.WIFI = 2;
|
Connection.WIFI = "wifi";
|
||||||
Connection.CELL_2G = 3;
|
Connection.CELL_2G = "2g";
|
||||||
Connection.CELL_3G = 4;
|
Connection.CELL_3G = "3g";
|
||||||
Connection.CELL_4G = 5;
|
Connection.CELL_4G = "4g";
|
||||||
Connection.NONE = 20;
|
Connection.NONE = "none";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get connection info
|
* Get connection info
|
||||||
|
@ -99,7 +99,7 @@ PhoneGap.Channel.prototype.subscribe = function(f, c, g) {
|
|||||||
if (f === null) { return; }
|
if (f === null) { return; }
|
||||||
|
|
||||||
var func = f;
|
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++;
|
g = g || func.observer_guid || f.observer_guid || this.guid++;
|
||||||
func.observer_guid = g;
|
func.observer_guid = g;
|
||||||
@ -120,7 +120,7 @@ PhoneGap.Channel.prototype.subscribeOnce = function(f, c) {
|
|||||||
_this.unsubscribe(g);
|
_this.unsubscribe(g);
|
||||||
};
|
};
|
||||||
if (this.fired) {
|
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);
|
f.apply(this, this.fireArgs);
|
||||||
} else {
|
} else {
|
||||||
g = this.subscribe(m);
|
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.
|
* Unsubscribes the function with the given guid from the channel.
|
||||||
*/
|
*/
|
||||||
PhoneGap.Channel.prototype.unsubscribe = function(g) {
|
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;
|
this.handlers[g] = null;
|
||||||
delete this.handlers[g];
|
delete this.handlers[g];
|
||||||
};
|
};
|
||||||
@ -147,7 +147,7 @@ PhoneGap.Channel.prototype.fire = function(e) {
|
|||||||
for (item in this.handlers) {
|
for (item in this.handlers) {
|
||||||
if (this.handlers.hasOwnProperty(item)) {
|
if (this.handlers.hasOwnProperty(item)) {
|
||||||
handler = this.handlers[item];
|
handler = this.handlers[item];
|
||||||
if (handler instanceof Function) {
|
if (typeof handler === "function") {
|
||||||
rv = (handler.apply(this, arguments) === false);
|
rv = (handler.apply(this, arguments) === false);
|
||||||
fail = fail || rv;
|
fail = fail || rv;
|
||||||
}
|
}
|
||||||
@ -344,10 +344,13 @@ PhoneGap.Channel.join(function() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var polling = prompt("usePolling", "gap_callbackServer:");
|
var polling = prompt("usePolling", "gap_callbackServer:");
|
||||||
|
PhoneGap.UsePolling = polling;
|
||||||
if (polling == "true") {
|
if (polling == "true") {
|
||||||
|
PhoneGap.UsePolling = true;
|
||||||
PhoneGap.JSCallbackPolling();
|
PhoneGap.JSCallbackPolling();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
PhoneGap.UsePolling = false;
|
||||||
PhoneGap.JSCallback();
|
PhoneGap.JSCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -507,7 +510,7 @@ PhoneGap.clone = function(obj) {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj instanceof Function) {
|
if (typeof obj === "function") {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,8 +770,8 @@ PhoneGap.JSCallback = function() {
|
|||||||
// If callback has JavaScript statement to execute
|
// If callback has JavaScript statement to execute
|
||||||
if (xmlhttp.status === 200) {
|
if (xmlhttp.status === 200) {
|
||||||
|
|
||||||
// Need to url decode the response and replace %20 with a space
|
// Need to url decode the response
|
||||||
var msg = decodeURIComponent(xmlhttp.responseText.replace(/\+/g, '%20'));
|
var msg = decodeURIComponent(xmlhttp.responseText);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
try {
|
try {
|
||||||
var t = eval(msg);
|
var t = eval(msg);
|
||||||
@ -802,13 +805,11 @@ PhoneGap.JSCallback = function() {
|
|||||||
console.log("JSCallback Error: Bad request. Stopping callbacks.");
|
console.log("JSCallback Error: Bad request. Stopping callbacks.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If error, restart callback server
|
// If error, revert to polling
|
||||||
else {
|
else {
|
||||||
console.log("JSCallback Error: Request failed.");
|
console.log("JSCallback Error: Request failed.");
|
||||||
prompt("restartServer", "gap_callbackServer:");
|
PhoneGap.UsePolling = true;
|
||||||
PhoneGap.JSCallbackPort = null;
|
PhoneGap.JSCallbackPolling();
|
||||||
PhoneGap.JSCallbackToken = null;
|
|
||||||
setTimeout(PhoneGap.JSCallback, 100);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -935,7 +936,11 @@ PhoneGap.includeJavascript = function(jsfile, successCallback) {
|
|||||||
*/
|
*/
|
||||||
var PluginManager = {
|
var PluginManager = {
|
||||||
addService: function(serviceType, className) {
|
addService: function(serviceType, className) {
|
||||||
|
try {
|
||||||
navigator.app.addService(serviceType, className);
|
navigator.app.addService(serviceType, className);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Error adding service "+serviceType+": "+e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title></title>
|
<title></title>
|
||||||
<script src="phonegap.0.9.5.min.js"></script>
|
<script src="phonegap.0.9.6.1.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
@ -10,5 +10,5 @@
|
|||||||
# Indicates whether an apk should be generated for each density.
|
# Indicates whether an apk should be generated for each density.
|
||||||
split.density=false
|
split.density=false
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-8
|
target=android-12
|
||||||
apk-configurations=
|
apk-configurations=
|
||||||
|
@ -12,6 +12,7 @@ import org.json.JSONException;
|
|||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import com.phonegap.api.Plugin;
|
import com.phonegap.api.Plugin;
|
||||||
import com.phonegap.api.PluginResult;
|
import com.phonegap.api.PluginResult;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class exposes methods in DroidGap that can be called from JavaScript.
|
* 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 {
|
public void loadUrl(String url, JSONObject props) throws JSONException {
|
||||||
System.out.println("App.loadUrl("+url+","+props+")");
|
System.out.println("App.loadUrl("+url+","+props+")");
|
||||||
int wait = 0;
|
int wait = 0;
|
||||||
|
boolean usePhoneGap = true;
|
||||||
|
boolean clearPrev = false;
|
||||||
|
|
||||||
// If there are properties, then set them on the Activity
|
// If there are properties, then set them on the Activity
|
||||||
|
HashMap<String, Object> params = new HashMap<String, Object>();
|
||||||
if (props != null) {
|
if (props != null) {
|
||||||
JSONArray keys = props.names();
|
JSONArray keys = props.names();
|
||||||
for (int i=0; i<keys.length(); i++) {
|
for (int i=0; i<keys.length(); i++) {
|
||||||
@ -92,32 +96,43 @@ public class App extends Plugin {
|
|||||||
if (key.equals("wait")) {
|
if (key.equals("wait")) {
|
||||||
wait = props.getInt(key);
|
wait = props.getInt(key);
|
||||||
}
|
}
|
||||||
|
else if (key.equalsIgnoreCase("usephonegap")) {
|
||||||
|
usePhoneGap = props.getBoolean(key);
|
||||||
|
}
|
||||||
|
else if (key.equalsIgnoreCase("clearprev")) {
|
||||||
|
clearPrev = props.getBoolean(key);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
Object value = props.get(key);
|
Object value = props.get(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (value.getClass().equals(String.class)) {
|
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)) {
|
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)) {
|
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 property, then delay loading
|
||||||
|
|
||||||
if (wait > 0) {
|
if (wait > 0) {
|
||||||
((DroidGap)this.ctx).loadUrl(url, wait);
|
try {
|
||||||
|
synchronized(this) {
|
||||||
|
this.wait(wait);
|
||||||
}
|
}
|
||||||
else {
|
} catch (InterruptedException e) {
|
||||||
((DroidGap)this.ctx).loadUrl(url);
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
((DroidGap)this.ctx).showWebPage(url, usePhoneGap, clearPrev, params);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel loadUrl before it has been loaded.
|
* Cancel loadUrl before it has been loaded.
|
||||||
|
@ -73,12 +73,12 @@ public class AudioHandler extends Plugin {
|
|||||||
this.stopPlayingAudio(args.getString(0));
|
this.stopPlayingAudio(args.getString(0));
|
||||||
}
|
}
|
||||||
else if (action.equals("getCurrentPositionAudio")) {
|
else if (action.equals("getCurrentPositionAudio")) {
|
||||||
long l = this.getCurrentPositionAudio(args.getString(0));
|
float f = this.getCurrentPositionAudio(args.getString(0));
|
||||||
return new PluginResult(status, l);
|
return new PluginResult(status, f);
|
||||||
}
|
}
|
||||||
else if (action.equals("getDurationAudio")) {
|
else if (action.equals("getDurationAudio")) {
|
||||||
long l = this.getDurationAudio(args.getString(0), args.getString(1));
|
float f = this.getDurationAudio(args.getString(0), args.getString(1));
|
||||||
return new PluginResult(status, l);
|
return new PluginResult(status, f);
|
||||||
}
|
}
|
||||||
else if (action.equals("release")) {
|
else if (action.equals("release")) {
|
||||||
boolean b = this.release(args.getString(0));
|
boolean b = this.release(args.getString(0));
|
||||||
@ -230,10 +230,10 @@ public class AudioHandler extends Plugin {
|
|||||||
* @param id The id of the audio player
|
* @param id The id of the audio player
|
||||||
* @return position in msec
|
* @return position in msec
|
||||||
*/
|
*/
|
||||||
public long getCurrentPositionAudio(String id) {
|
public float getCurrentPositionAudio(String id) {
|
||||||
AudioPlayer audio = this.players.get(id);
|
AudioPlayer audio = this.players.get(id);
|
||||||
if (audio != null) {
|
if (audio != null) {
|
||||||
return(audio.getCurrentPosition());
|
return(audio.getCurrentPosition()/1000.0f);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -245,7 +245,7 @@ public class AudioHandler extends Plugin {
|
|||||||
* @param file The name of the audio file.
|
* @param file The name of the audio file.
|
||||||
* @return The duration in msec.
|
* @return The duration in msec.
|
||||||
*/
|
*/
|
||||||
public long getDurationAudio(String id, String file) {
|
public float getDurationAudio(String id, String file) {
|
||||||
|
|
||||||
// Get audio file
|
// Get audio file
|
||||||
AudioPlayer audio = this.players.get(id);
|
AudioPlayer audio = this.players.get(id);
|
||||||
|
@ -15,6 +15,7 @@ import android.media.MediaPlayer.OnErrorListener;
|
|||||||
import android.media.MediaRecorder;
|
import android.media.MediaRecorder;
|
||||||
import android.media.MediaPlayer.OnCompletionListener;
|
import android.media.MediaPlayer.OnCompletionListener;
|
||||||
import android.media.MediaPlayer.OnPreparedListener;
|
import android.media.MediaPlayer.OnPreparedListener;
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements the audio playback and recording capabilities used by PhoneGap.
|
* 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 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 int state = MEDIA_NONE; // State of recording or playback
|
||||||
private String audioFile = null; // File name to play or record to
|
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 MediaRecorder recorder = null; // Audio recording object
|
||||||
private String tempFile = null; // Temporary recording file name
|
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) {
|
public AudioPlayer(AudioHandler handler, String id) {
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3";
|
||||||
// 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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -209,7 +207,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
this.mPlayer.prepare();
|
this.mPlayer.prepare();
|
||||||
|
|
||||||
// Get duration
|
// Get duration
|
||||||
this.duration = this.mPlayer.getDuration();
|
this.duration = getDurationInSeconds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
@ -319,7 +317,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
* -1=can't be determined
|
* -1=can't be determined
|
||||||
* -2=not allowed
|
* -2=not allowed
|
||||||
*/
|
*/
|
||||||
public long getDuration(String file) {
|
public float getDuration(String file) {
|
||||||
|
|
||||||
// Can't get duration of recording
|
// Can't get duration of recording
|
||||||
if (this.recorder != null) {
|
if (this.recorder != null) {
|
||||||
@ -362,7 +360,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save off duration
|
// Save off duration
|
||||||
this.duration = this.mPlayer.getDuration();
|
this.duration = getDurationInSeconds();
|
||||||
this.prepareOnly = false;
|
this.prepareOnly = false;
|
||||||
|
|
||||||
// Send status notification to JavaScript
|
// 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
|
* Callback to be invoked when there has been an error during an asynchronous operation
|
||||||
* (other errors will throw exceptions at method call time).
|
* (other errors will throw exceptions at method call time).
|
||||||
|
@ -11,11 +11,14 @@ import java.io.BufferedReader;
|
|||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.LinkedList;
|
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.
|
* 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
|
* 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 {
|
public class CallbackServer implements Runnable {
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "CallbackServer";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of JavaScript statements to be sent to JavaScript.
|
* 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");
|
//System.out.println("CallbackServer -- sending item");
|
||||||
response = "HTTP/1.1 200 OK\r\n\r\n";
|
response = "HTTP/1.1 200 OK\r\n\r\n";
|
||||||
String js = this.getJavascript();
|
String js = this.getJavascript();
|
||||||
if (js != null)
|
if (js != null) {
|
||||||
response += URLEncoder.encode(js, "UTF-8");
|
response += encode(js, "UTF-8");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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 */
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,14 @@ public class CameraLauncher extends Plugin {
|
|||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
try {
|
try {
|
||||||
// Read in bitmap of captured image
|
// 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 sending base64 image back
|
||||||
if (destType == DATA_URL) {
|
if (destType == DATA_URL) {
|
||||||
|
@ -178,12 +178,14 @@ public abstract class ContactAccessor {
|
|||||||
protected String getJsonString(JSONObject obj, String property) {
|
protected String getJsonString(JSONObject obj, String property) {
|
||||||
String value = null;
|
String value = null;
|
||||||
try {
|
try {
|
||||||
|
if (obj != null) {
|
||||||
value = obj.getString(property);
|
value = obj.getString(property);
|
||||||
if (value.equals("null")) {
|
if (value.equals("null")) {
|
||||||
Log.d(LOG_TAG, property + " is string called 'null'");
|
Log.d(LOG_TAG, property + " is string called 'null'");
|
||||||
value = null;
|
value = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (JSONException e) {
|
catch (JSONException e) {
|
||||||
Log.d(LOG_TAG, "Could not get = " + e.getMessage());
|
Log.d(LOG_TAG, "Could not get = " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
@ -1420,7 +1420,6 @@ public class ContactAccessorSdk5 extends ContactAccessor {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add urls
|
// Add urls
|
||||||
JSONArray websites = null;
|
JSONArray websites = null;
|
||||||
try {
|
try {
|
||||||
@ -1473,7 +1472,6 @@ public class ContactAccessorSdk5 extends ContactAccessor {
|
|||||||
Log.e(LOG_TAG, e.getMessage(), e);
|
Log.e(LOG_TAG, e.getMessage(), e);
|
||||||
retVal = false;
|
retVal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,13 +14,11 @@ import org.json.JSONObject;
|
|||||||
import com.phonegap.api.PhonegapActivity;
|
import com.phonegap.api.PhonegapActivity;
|
||||||
import com.phonegap.api.Plugin;
|
import com.phonegap.api.Plugin;
|
||||||
import com.phonegap.api.PluginResult;
|
import com.phonegap.api.PluginResult;
|
||||||
import android.content.Context;
|
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
|
|
||||||
public class Device extends Plugin {
|
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 platform = "Android"; // Device OS
|
||||||
public static String uuid; // Device UUID
|
public static String uuid; // Device UUID
|
||||||
|
|
||||||
@ -117,33 +115,12 @@ public class Device extends Plugin {
|
|||||||
return Device.phonegapVersion;
|
return Device.phonegapVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLine1Number(){
|
public String getModel() {
|
||||||
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()
|
|
||||||
{
|
|
||||||
String model = android.os.Build.MODEL;
|
String model = android.os.Build.MODEL;
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
public String getProductName()
|
|
||||||
{
|
public String getProductName() {
|
||||||
String productname = android.os.Build.PRODUCT;
|
String productname = android.os.Build.PRODUCT;
|
||||||
return productname;
|
return productname;
|
||||||
}
|
}
|
||||||
@ -158,8 +135,7 @@ public class Device extends Plugin {
|
|||||||
return osversion;
|
return osversion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSDKVersion()
|
public String getSDKVersion() {
|
||||||
{
|
|
||||||
String sdkversion = android.os.Build.VERSION.SDK;
|
String sdkversion = android.os.Build.VERSION.SDK;
|
||||||
return sdkversion;
|
return sdkversion;
|
||||||
}
|
}
|
||||||
|
@ -7,38 +7,49 @@
|
|||||||
*/
|
*/
|
||||||
package com.phonegap;
|
package com.phonegap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
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.content.res.Configuration;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.net.http.SslError;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.Display;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.webkit.JsResult;
|
import android.webkit.GeolocationPermissions.Callback;
|
||||||
import android.webkit.WebChromeClient;
|
|
||||||
import android.webkit.JsPromptResult;
|
import android.webkit.JsPromptResult;
|
||||||
|
import android.webkit.JsResult;
|
||||||
|
import android.webkit.SslErrorHandler;
|
||||||
|
import android.webkit.WebChromeClient;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
|
import android.webkit.WebSettings.LayoutAlgorithm;
|
||||||
import android.webkit.WebStorage;
|
import android.webkit.WebStorage;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
import android.webkit.GeolocationPermissions.Callback;
|
import android.widget.EditText;
|
||||||
import android.webkit.WebSettings.LayoutAlgorithm;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.phonegap.api.PhonegapActivity;
|
||||||
import com.phonegap.api.Plugin;
|
import com.phonegap.api.Plugin;
|
||||||
import com.phonegap.api.PluginManager;
|
import com.phonegap.api.PluginManager;
|
||||||
import com.phonegap.api.PhonegapActivity;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is the main Android activity that represents the PhoneGap
|
* This class is the main Android activity that represents the PhoneGap
|
||||||
@ -119,10 +130,15 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
protected boolean clearHistory = false;
|
protected boolean clearHistory = false;
|
||||||
|
|
||||||
// The initial URL for our app
|
// The initial URL for our app
|
||||||
|
// ie http://server/path/index.html#abc?query
|
||||||
private String url;
|
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
|
// The base of the initial URL for our app
|
||||||
private String baseUrl;
|
private String baseUrl = null;
|
||||||
|
|
||||||
// Plugin to call when activity result is received
|
// Plugin to call when activity result is received
|
||||||
protected Plugin activityResultCallback = null;
|
protected Plugin activityResultCallback = null;
|
||||||
@ -168,7 +184,11 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
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!
|
// 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.setOrientation(LinearLayout.VERTICAL);
|
||||||
root.setBackgroundColor(Color.BLACK);
|
root.setBackgroundColor(Color.BLACK);
|
||||||
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
||||||
@ -330,13 +350,16 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
*/
|
*/
|
||||||
public void loadUrl(final String url) {
|
public void loadUrl(final String url) {
|
||||||
System.out.println("loadUrl("+url+")");
|
System.out.println("loadUrl("+url+")");
|
||||||
|
this.urlFile = this.getUrlFile(url);
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
if (this.baseUrl == null) {
|
||||||
int i = url.lastIndexOf('/');
|
int i = url.lastIndexOf('/');
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
this.baseUrl = url.substring(0, i);
|
this.baseUrl = url.substring(0, i+1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.baseUrl = this.url;
|
this.baseUrl = this.url + "/";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
System.out.println("url="+url+" baseUrl="+baseUrl);
|
System.out.println("url="+url+" baseUrl="+baseUrl);
|
||||||
|
|
||||||
@ -608,17 +631,28 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
// Send pause event to JavaScript
|
// Send pause event to JavaScript
|
||||||
this.appView.loadUrl("javascript:try{PhoneGap.onPause.fire();}catch(e){};");
|
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 app doesn't want to run in background
|
||||||
if (!this.keepRunning) {
|
if (!this.keepRunning) {
|
||||||
|
|
||||||
// Forward to plugins
|
|
||||||
this.pluginManager.onPause();
|
|
||||||
|
|
||||||
// Pause JavaScript timers (including setInterval)
|
// Pause JavaScript timers (including setInterval)
|
||||||
this.appView.pauseTimers();
|
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
|
@Override
|
||||||
/**
|
/**
|
||||||
* Called when the activity will start interacting with the user.
|
* Called when the activity will start interacting with the user.
|
||||||
@ -632,6 +666,9 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
// Send resume event to JavaScript
|
// Send resume event to JavaScript
|
||||||
this.appView.loadUrl("javascript:try{PhoneGap.onResume.fire();}catch(e){};");
|
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 app doesn't want to run in background
|
||||||
if (!this.keepRunning || this.activityResultKeepRunning) {
|
if (!this.keepRunning || this.activityResultKeepRunning) {
|
||||||
|
|
||||||
@ -641,9 +678,6 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
this.activityResultKeepRunning = false;
|
this.activityResultKeepRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward to plugins
|
|
||||||
this.pluginManager.onResume();
|
|
||||||
|
|
||||||
// Resume JavaScript timers (including setInterval)
|
// Resume JavaScript timers (including setInterval)
|
||||||
this.appView.resumeTimers();
|
this.appView.resumeTimers();
|
||||||
}
|
}
|
||||||
@ -670,9 +704,6 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
// Forward to plugins
|
// Forward to plugins
|
||||||
this.pluginManager.onDestroy();
|
this.pluginManager.onDestroy();
|
||||||
|
|
||||||
if (this.callbackServer != null) {
|
|
||||||
this.callbackServer.destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,13 +727,82 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
this.callbackServer.sendJavascript(statement);
|
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
|
* Provides a hook for calling "alert" from javascript. Useful for
|
||||||
* debugging your javascript.
|
* debugging your javascript.
|
||||||
*/
|
*/
|
||||||
public class GapClient extends WebChromeClient {
|
public class GapClient extends WebChromeClient {
|
||||||
|
|
||||||
private Context ctx;
|
private DroidGap ctx;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -710,7 +810,7 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
* @param ctx
|
* @param ctx
|
||||||
*/
|
*/
|
||||||
public GapClient(Context ctx) {
|
public GapClient(Context ctx) {
|
||||||
this.ctx = ctx;
|
this.ctx = (DroidGap)ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -783,9 +883,16 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
|
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
|
// Calling PluginManager.exec() to call a native service using
|
||||||
// prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
|
// 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;
|
JSONArray array;
|
||||||
try {
|
try {
|
||||||
array = new JSONArray(defaultValue.substring(4));
|
array = new JSONArray(defaultValue.substring(4));
|
||||||
@ -801,13 +908,13 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Polling for JavaScript messages
|
// Polling for JavaScript messages
|
||||||
else if (defaultValue.equals("gap_poll:")) {
|
else if (reqOk && defaultValue.equals("gap_poll:")) {
|
||||||
String r = callbackServer.getJavascript();
|
String r = callbackServer.getJavascript();
|
||||||
result.confirm(r);
|
result.confirm(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calling into CallbackServer
|
// Calling into CallbackServer
|
||||||
else if (defaultValue.equals("gap_callbackServer:")) {
|
else if (reqOk && defaultValue.equals("gap_callbackServer:")) {
|
||||||
String r = "";
|
String r = "";
|
||||||
if (message.equals("usePolling")) {
|
if (message.equals("usePolling")) {
|
||||||
r = ""+callbackServer.usePolling();
|
r = ""+callbackServer.usePolling();
|
||||||
@ -1022,17 +1129,18 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
// All else
|
// All else
|
||||||
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
|
// If our app or file:, then load into our webview
|
||||||
// NOTE: This replaces our app with new URL. When BACK is pressed,
|
// NOTE: This replaces our app with new URL. When BACK is pressed,
|
||||||
// our app is reloaded and restarted. All state is lost.
|
// our app is reloaded and restarted. All state is lost.
|
||||||
if (this.ctx.loadInWebView || url.startsWith("file://") || this.ctx.baseUrl.equals(newBaseUrl)) {
|
if (this.ctx.loadInWebView || url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0) {
|
||||||
this.ctx.appView.loadUrl(url);
|
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
|
// 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
|
// 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
|
// 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.
|
// from the JS side when the JS gets to that code.
|
||||||
|
if (!url.equals("about:blank")) {
|
||||||
appView.loadUrl("javascript:try{ PhoneGap.onNativeReady.fire();}catch(e){_nativeReady = true;}");
|
appView.loadUrl("javascript:try{ PhoneGap.onNativeReady.fire();}catch(e){_nativeReady = true;}");
|
||||||
|
}
|
||||||
|
|
||||||
// Make app view visible
|
// Make app view visible
|
||||||
appView.setVisibility(View.VISIBLE);
|
appView.setVisibility(View.VISIBLE);
|
||||||
@ -1081,6 +1191,13 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
this.ctx.clearHistory = false;
|
this.ctx.clearHistory = false;
|
||||||
this.ctx.appView.clearHistory();
|
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
|
// Handle error
|
||||||
this.ctx.onReceivedError(errorCode, description, failingUrl);
|
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 back key is bound, then send event to JavaScript
|
||||||
if (this.bound) {
|
if (this.bound) {
|
||||||
this.appView.loadUrl("javascript:PhoneGap.fireEvent('backbutton');");
|
this.appView.loadUrl("javascript:PhoneGap.fireEvent('backbutton');");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not bound
|
// 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
|
// Go to previous page in webview if it is possible to go back
|
||||||
if (this.appView.canGoBack()) {
|
if (this.appView.canGoBack()) {
|
||||||
this.appView.goBack();
|
this.appView.goBack();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not, then invoke behavior of super class
|
// If not, then invoke behavior of super class
|
||||||
@ -1145,11 +1285,13 @@ public class DroidGap extends PhonegapActivity {
|
|||||||
// If menu key
|
// If menu key
|
||||||
else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||||
this.appView.loadUrl("javascript:PhoneGap.fireEvent('menubutton');");
|
this.appView.loadUrl("javascript:PhoneGap.fireEvent('menubutton');");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If search key
|
// If search key
|
||||||
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
||||||
this.appView.loadUrl("javascript:PhoneGap.fireEvent('searchbutton');");
|
this.appView.loadUrl("javascript:PhoneGap.fireEvent('searchbutton');");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ package com.phonegap;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.URLDecoder;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
@ -229,15 +230,16 @@ public class FileUtils extends Plugin {
|
|||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
private JSONObject resolveLocalFileSystemURI(String url) throws IOException, 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
|
// Test to see if this is a valid URL first
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
URL testUrl = new URL(url);
|
URL testUrl = new URL(decoded);
|
||||||
|
|
||||||
File fp = null;
|
File fp = null;
|
||||||
if (url.startsWith("file://")) {
|
if (decoded.startsWith("file://")) {
|
||||||
fp = new File(url.substring(7, url.length()));
|
fp = new File(decoded.substring(7, decoded.length()));
|
||||||
} else {
|
} else {
|
||||||
fp = new File(url);
|
fp = new File(decoded);
|
||||||
}
|
}
|
||||||
if (!fp.exists()) {
|
if (!fp.exists()) {
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
@ -411,7 +413,7 @@ public class FileUtils extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check to make sure we are not copying the directory into itself
|
// 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");
|
throw new InvalidModificationException("Can't copy itself into itself");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,6 +437,26 @@ public class FileUtils extends Plugin {
|
|||||||
return getEntry(destinationDir);
|
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
|
* Move a file
|
||||||
*
|
*
|
||||||
@ -480,8 +502,8 @@ public class FileUtils extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check to make sure we are not copying the directory into itself
|
// 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");
|
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.
|
// If the destination directory already exists and is empty then delete it. This is according to spec.
|
||||||
|
@ -11,7 +11,6 @@ import org.apache.http.client.methods.HttpGet;
|
|||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import com.phonegap.api.PhonegapActivity;
|
import com.phonegap.api.PhonegapActivity;
|
||||||
import com.phonegap.api.Plugin;
|
import com.phonegap.api.Plugin;
|
||||||
@ -21,8 +20,8 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.net.*;
|
import android.net.ConnectivityManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.net.NetworkInfo;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class NetworkManager extends Plugin {
|
public class NetworkManager extends Plugin {
|
||||||
@ -46,24 +45,26 @@ public class NetworkManager extends Plugin {
|
|||||||
public static final String LTE = "lte";
|
public static final String LTE = "lte";
|
||||||
public static final String UMB = "umb";
|
public static final String UMB = "umb";
|
||||||
// return types
|
// return types
|
||||||
public static final int TYPE_UNKNOWN = 0;
|
public static final String TYPE_UNKNOWN = "unknown";
|
||||||
public static final int TYPE_ETHERNET = 1;
|
public static final String TYPE_ETHERNET = "ethernet";
|
||||||
public static final int TYPE_WIFI = 2;
|
public static final String TYPE_WIFI = "wifi";
|
||||||
public static final int TYPE_2G = 3;
|
public static final String TYPE_2G = "2g";
|
||||||
public static final int TYPE_3G = 4;
|
public static final String TYPE_3G = "3g";
|
||||||
public static final int TYPE_4G = 5;
|
public static final String TYPE_4G = "4g";
|
||||||
public static final int TYPE_NONE = 20;
|
public static final String TYPE_NONE = "none";
|
||||||
|
|
||||||
private static final String LOG_TAG = "NetworkManager";
|
private static final String LOG_TAG = "NetworkManager";
|
||||||
|
|
||||||
private String connectionCallbackId;
|
private String connectionCallbackId;
|
||||||
|
|
||||||
ConnectivityManager sockMan;
|
ConnectivityManager sockMan;
|
||||||
TelephonyManager telephonyManager;
|
BroadcastReceiver receiver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public NetworkManager() {
|
public NetworkManager() {
|
||||||
|
this.receiver = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,17 +76,21 @@ public class NetworkManager extends Plugin {
|
|||||||
public void setContext(PhonegapActivity ctx) {
|
public void setContext(PhonegapActivity ctx) {
|
||||||
super.setContext(ctx);
|
super.setContext(ctx);
|
||||||
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
|
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
|
// We need to listen to connectivity events to update navigator.connection
|
||||||
IntentFilter intentFilter = new IntentFilter() ;
|
IntentFilter intentFilter = new IntentFilter() ;
|
||||||
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||||
ctx.registerReceiver(new BroadcastReceiver() {
|
if (this.receiver == null) {
|
||||||
|
this.receiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
|
updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
|
||||||
}
|
}
|
||||||
}, intentFilter);
|
};
|
||||||
|
ctx.registerReceiver(this.receiver, intentFilter);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,6 +141,19 @@ public class NetworkManager extends Plugin {
|
|||||||
return false;
|
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
|
// LOCAL METHODS
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
@ -148,10 +166,8 @@ public class NetworkManager extends Plugin {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private void updateConnectionInfo(NetworkInfo info) {
|
private void updateConnectionInfo(NetworkInfo info) {
|
||||||
JSONObject connection = this.getConnectionInfo(info);
|
// send update to javascript "navigator.network.connection"
|
||||||
|
sendUpdate(this.getConnectionInfo(info));
|
||||||
// send update to javascript "navigator.connection"
|
|
||||||
sendUpdate(connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,40 +176,18 @@ public class NetworkManager extends Plugin {
|
|||||||
* @param info the current active network info
|
* @param info the current active network info
|
||||||
* @return a JSONObject that represents the network info
|
* @return a JSONObject that represents the network info
|
||||||
*/
|
*/
|
||||||
private JSONObject getConnectionInfo(NetworkInfo info) {
|
private String getConnectionInfo(NetworkInfo info) {
|
||||||
JSONObject connection = new JSONObject();
|
String type = TYPE_NONE;
|
||||||
|
|
||||||
try {
|
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
// If we are not connected to any network set type to none
|
// If we are not connected to any network set type to none
|
||||||
if (!info.isConnected()) {
|
if (!info.isConnected()) {
|
||||||
connection.put("type", TYPE_NONE);
|
type = TYPE_NONE;
|
||||||
connection.put("homeNW", null);
|
|
||||||
connection.put("currentNW", null);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If we are connected check which type
|
type = getType(info);
|
||||||
// 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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return type;
|
||||||
}
|
|
||||||
catch (JSONException e) {
|
|
||||||
// this should never happen
|
|
||||||
Log.e(LOG_TAG, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,8 +195,8 @@ public class NetworkManager extends Plugin {
|
|||||||
*
|
*
|
||||||
* @param connection the network info to set as navigator.connection
|
* @param connection the network info to set as navigator.connection
|
||||||
*/
|
*/
|
||||||
private void sendUpdate(JSONObject connection) {
|
private void sendUpdate(String type) {
|
||||||
PluginResult result = new PluginResult(PluginResult.Status.OK, connection);
|
PluginResult result = new PluginResult(PluginResult.Status.OK, type);
|
||||||
result.setKeepCallback(true);
|
result.setKeepCallback(true);
|
||||||
this.success(result, this.connectionCallbackId);
|
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.
|
* @param info the network info so we can determine connection type.
|
||||||
* @return the type of mobile network we are on
|
* @return the type of mobile network we are on
|
||||||
*/
|
*/
|
||||||
private int getType(NetworkInfo info) {
|
private String getType(NetworkInfo info) {
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
String type = info.getTypeName();
|
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();
|
type = info.getSubtypeName();
|
||||||
if (type.toLowerCase().equals(GSM) ||
|
if (type.toLowerCase().equals(GSM) ||
|
||||||
type.toLowerCase().equals(GPRS) ||
|
type.toLowerCase().equals(GPRS) ||
|
||||||
@ -278,7 +275,7 @@ public class NetworkManager extends Plugin {
|
|||||||
public int isReachable(String uri, boolean isIpAddress) {
|
public int isReachable(String uri, boolean isIpAddress) {
|
||||||
int reachable = NOT_REACHABLE;
|
int reachable = NOT_REACHABLE;
|
||||||
|
|
||||||
if (uri.indexOf("http://") == -1) {
|
if (uri.indexOf("http://") == -1 && uri.indexOf("https://") == -1) {
|
||||||
uri = "http://" + uri;
|
uri = "http://" + uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,13 +54,17 @@ public interface IPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the system is about to start resuming a previous activity.
|
* 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.
|
* 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.
|
* The final call you receive before your activity is destroyed.
|
||||||
|
@ -64,14 +64,24 @@ public abstract class Plugin implements IPlugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the system is about to start resuming a previous activity.
|
* 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.
|
* 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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +13,7 @@ import java.util.Map.Entry;
|
|||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -229,27 +230,31 @@ public final class PluginManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the system is about to start resuming a previous activity.
|
* 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.Set<Entry<String,Plugin>> s = this.plugins.entrySet();
|
||||||
java.util.Iterator<Entry<String,Plugin>> it = s.iterator();
|
java.util.Iterator<Entry<String,Plugin>> it = s.iterator();
|
||||||
while(it.hasNext()) {
|
while(it.hasNext()) {
|
||||||
Entry<String,Plugin> entry = it.next();
|
Entry<String,Plugin> entry = it.next();
|
||||||
Plugin plugin = entry.getValue();
|
Plugin plugin = entry.getValue();
|
||||||
plugin.onPause();
|
plugin.onPause(multitasking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the activity will start interacting with the user.
|
* 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.Set<Entry<String,Plugin>> s = this.plugins.entrySet();
|
||||||
java.util.Iterator<Entry<String,Plugin>> it = s.iterator();
|
java.util.Iterator<Entry<String,Plugin>> it = s.iterator();
|
||||||
while(it.hasNext()) {
|
while(it.hasNext()) {
|
||||||
Entry<String,Plugin> entry = it.next();
|
Entry<String,Plugin> entry = it.next();
|
||||||
Plugin plugin = entry.getValue();
|
Plugin plugin = entry.getValue();
|
||||||
plugin.onResume();
|
plugin.onResume(multitasking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,4 +270,17 @@ public final class PluginManager {
|
|||||||
plugin.onDestroy();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -88,7 +88,7 @@ class Classic
|
|||||||
|
|
||||||
# copies stuff from src directory into the android project directory (@path)
|
# copies stuff from src directory into the android project directory (@path)
|
||||||
def copy_libs
|
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")
|
framework_res_dir = File.join(@framework_dir, "res")
|
||||||
app_res_dir = File.join(@path, "res")
|
app_res_dir = File.join(@path, "res")
|
||||||
# copies in the jar
|
# copies in the jar
|
||||||
|
@ -33,12 +33,19 @@ class Update
|
|||||||
# TODO need to allow for www import inc icon
|
# TODO need to allow for www import inc icon
|
||||||
def copy_libs
|
def copy_libs
|
||||||
puts "Copying over libraries and assets..."
|
puts "Copying over libraries and assets..."
|
||||||
|
version = IO.read(File.join(@framework_dir, '../VERSION'))
|
||||||
|
|
||||||
FileUtils.mkdir_p File.join(@path, "libs")
|
FileUtils.cp File.join(@framework_dir, "phonegap.#{ version }.jar"), File.join(@path, "libs")
|
||||||
FileUtils.cp File.join(@framework_dir, "phonegap.jar"), File.join(@path, "libs")
|
|
||||||
|
|
||||||
FileUtils.mkdir_p File.join(@path, "assets", "www")
|
# concat JS and put into www folder. this can be overridden in the config.xml via @app_js_dir
|
||||||
FileUtils.cp File.join(@framework_dir, "assets", "www", "phonegap.js"), File.join(@path, "assets", "www")
|
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
|
||||||
#
|
#
|
||||||
end
|
end
|
Loading…
Reference in New Issue
Block a user